У меня есть что-то, что работает сейчас. Он работает так, как я описал в своем комментарии к моему вопросу выше. Просто для того, чтобы повторить, я использую 2 пользовательских директивы, оба из которых основаны на ng-repeat. Первая построит структуру плоской таблицы с буквальными значениями в атрибуте class, чтобы указать глубину. Вторая директива использует эту информацию глубины, чтобы повторить элемент заполнения на соответствующее количество раз. Оба повторителя используют переход, чтобы минимизировать ограничения/зависимости от html. Единственное предостережение в том, что второму повторителю нужна информация о глубине, чтобы быть где-то в ее родословной внутри DOM.
Вот что шаблон HTML выглядит для создания дерева стол структуры я описал в моем вопросе:
<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>
я на основе моего пользовательского повторитель на this примере. Что отличает меня, так это то, что вы можете указать свойство «children», а логика директивы будет проверять это свойство на каждом элементе и рекурсивно переходить в него, если он есть, - хотя он присоединяет все новые элементы к одному и тому же родителю, плоская структура.
Это, вероятно, довольно неэффективно и может использовать некоторую оптимизацию - как и код в ссылке, которую я предоставил, она восстанавливает все, когда есть изменения.
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);
}
});
}
};
});
Второй - немного взломанный. Это также трансивер-повторитель. Он ищет вверх в DOM для атрибута класса глубины, анализирует значение глубины и добавляет себя много раз в родительский. Таким образом, он полностью зависит от этого класса глубины, заданного первой директивой. Вероятно, есть лучшие способы сделать это. Я также не стал настраивать часы или что-то в этом роде, поскольку это чисто косметическое.
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);
});
}
}
};
});
Это далеко не идеальный вариант, и мне придется потратить некоторое время на его улучшение. Я даже не уверен, что HTML, который я создаю, - лучший способ получить внешний вид, который я хочу, но он делает то, что я хочу, сохраняя при этом шаблон html, выглядящий достаточно элегантным.
По какой-либо причине это должен быть стол? вы можете попробовать распространить директиву как [angular-json-tree] (https://github.com/awendland/angular-json-tree), чтобы разрешить редактирование – haxxxton
Мне нужно несколько столбцов. Я не показывал их в моем примере для краткости. –
Что вы хотите достичь с помощью дополнительных столбцов? :) для редактирования/удаления/дублирования? вы, вероятно, могли бы работать с ui-popover или modal, если так – haxxxton