Ich habe etwas, das jetzt funktioniert. Es funktioniert so, wie ich es in meinem Kommentar zu meiner Frage oben beschrieben habe. Zur Erinnerung, ich verwende 2 benutzerdefinierte Direktiven, die beide auf ng-repeat basieren. Der erste erstellt eine flache Tabellenstruktur mit Literalwerten im Klassenattribut, um die Tiefe anzuzeigen. Die zweite Anweisung verwendet diese Tiefeninformationen, um das Padding-Element die entsprechende Anzahl von Wiederholungen zu wiederholen. Beide Repeater verwenden die Transclusion, um Beschränkungen/Abhängigkeiten von HTML zu minimieren. Der einzige Vorbehalt ist, dass der zweite Repeater die Tiefeninformationen benötigt, um irgendwo innerhalb seiner DOM-Herkunft zu sein.
Hier ist, was die HTML-Vorlage sieht aus wie für eine Baum Tabelle der Struktur produziert ich in meiner Frage beschrieben:
<table class="treetable" style="width: 40%;">
<tr class="treetable-node" my-repeat="item in things"
my-repeat-children="children">
<td>
<span my-repeat-padding class="treetable-node-indent"></span>
{{ item.name }}
</td>
<td>
{{ item.type }}
</td>
</tr>
</table>
ich anhand meines benutzerdefinierten Repeater auf this Beispiel. Was meins anders macht, ist, dass Sie eine "children" -Eigenschaft angeben können und die Direktivenlogik nach dieser Eigenschaft für jedes Element sucht und rekursiv in sie absteigt, wenn sie dort ist - obwohl sie alle neuen Elemente an das gleiche übergeordnete Element anfügt und mir den flache Struktur.
Es ist wahrscheinlich ziemlich ineffizient, und könnte einige Optimierung verwenden - wie der Code in der Verbindung, die ich zur Verfügung stellte, baut es alles auf, wenn es eine Änderung gibt.
myApp.directive("myRepeat", function($parse) {
return {
restrict: "A",
replace: true,
transclude: "element",
link: function (scope, element, attrs, controller, transclude) {
match = attrs.myRepeat.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/);
itemName = match[1];
collectionName = match[2];
childCollectionName = attrs["myRepeatChildren"];
parentElement = element.parent();
elements = [];
scope.$watchCollection(collectionName, function(collection) {
var i, block, childScope;
if (elements.length > 0) {
for(i=0; i<elements.length; i++) {
elements[i].el.remove();
elements[i].scope.$destroy();
};
elements = [];
}
var buildHtml = function(parent, itemList, depth=0) {
for (var i=0; i<itemList.length; i++) {
childScope = scope.$new();
childScope[itemName] = itemList[i];
transclude(childScope, function(clone) {
parentElement.append(clone);
block = {};
block.el = clone;
block.scope = childScope;
block.el.addClass("depth-" + depth);
elements.push(block);
});
/*Recurse if this item has children,
adding the sub-elements to the same
parent so we end up with a flat list*/
if(childCollectionName in itemList[i]) {
buildHtml(parentElement,
itemList[i][childCollectionName],
depth+1);
}
}
}
for (i=0; i<collection.length; i++) {
buildHtml(parentElement, collection);
}
});
}
};
});
Die zweite ist ein bisschen hacky. Es ist auch ein Transceiver. Es sucht im DOM nach dem Attribut für die Tiefenklasse nach oben, analysiert den Tiefenwert und fügt sich selbst oft in das Elternobjekt ein. Es hängt also vollständig von der Tiefenklasse ab, die von der ersten Direktive festgelegt wurde. Es gibt wahrscheinlich bessere Möglichkeiten, dies zu tun. Ich habe mir auch keine Mühe gemacht, eine Uhr oder ähnliches aufzustellen, da dies rein kosmetischer Natur ist.
myApp.directive("myRepeatPadding", function($parse) {
return {
restrict: "A",
replace: true,
transclude: "element",
terminal: true,
link: function (scope, element, attrs, controller, transclude) {
var getDepth = function(element) {
classes = element.attr("class");
if (classes) {
match = classes.match(/depth-([\d+])/);
if(match.length > 0) {
return match[1];
} else {
return getDepth(element.parent());
}
} else {
return getDepth(element.parent());
}
}
depth = getDepth(element);
for (var i=0; i<depth; i++) {
transclude(scope, function(clone) {
element.parent().prepend(clone);
block = {};
block.el = clone;
block.scope = scope;
elements.push(block);
});
}
}
};
});
Es ist bei weitem nicht perfekt und ich werde einige Zeit damit verbringen müssen, es zu verbessern. Ich bin mir nicht einmal sicher, ob der HTML-Code, den ich produziere, der beste Weg ist, um das gewünschte Aussehen zu erhalten - aber es macht so, wie ich es möchte, während die HTML-Vorlage einigermaßen elegant aussieht.
aus irgendeinem Grund muss dies eine Tabelle sein? Sie könnten versuchen, eine Direktive wie [angular-json-tree] (https://github.com/awendland/angular-json-tree) zu erweitern, um die Bearbeitung zu ermöglichen. – haxxxton
Ich brauche mehrere Spalten. Ich habe sie in meinem Beispiel der Kürze halber nicht gezeigt. –
Was möchten Sie mit den zusätzlichen Säulen erreichen? :) Tasten zum Bearbeiten/Löschen/Duplizieren? du könntest wahrscheinlich dasselbe mit ui-popovers oder einem modalen handhaben, wenn so – haxxxton