我有一个树视图,其中包含我试图填充的嵌套数组的对象。
A working plunker may be found here.
以下是代码结构的细分以及迄今为止我尝试过的内容。
在我的treeview.html视图中,我正在加载我创建的treeview指令: 我目前有两个只是为了测试绑定。在检查事件复选框之前,第二个不会填充。
<H3>Tree View Sameple</H3>
<div>
<h3>Treeview 1</h3>
<tree src="tree.treeData" iobj="object" filter="tree.getAggregateInfo(object, isSelected)"></tree>
<h3>Treeview 2 once object has been updated</h3>
<tree src="tree.treeData2" iobj="object" filter="tree.getAggregateInfo(object, isSelected)"></tree>
</div>
<hr/>
<p>javascript object data</p>
{{tree.treeData}}
底部绑定只显示js文件的输出。单击事件复选框时,在树视图中显示我正在模拟正在检索的新嵌套集合,该集合应作为树元素事件节点下的子元素插入。
以下是treeviewController.js
中使用的代码(function () {
angular.module('app')
.controller('treeviewController', ['$log', '$scope', '$timeout', treeviewController]);
function treeviewController($log, $scope, $timeout) {
var vm = this;
//storage container for last node selected in tree
vm.lastNodeSelected = '';
vm.treeData2 = {};//test container to reflect object once updated
//original data not an arry but an object holding an array
vm.treeData =
{
"children": [
{
"name": "Document Type",
"children": [
{
"name": "Incident",
"documentType": "Document Type",
"aggregateUponField": "_ocommon.documenttype",
"parent": "",
"count": 2950,
"children": null
},
{
"name": "Some Event",
"documentType": "Document Type",
"aggregateUponField": "_ocommon.documenttype",
"parent": "",
"count": 2736,
"children": [{
"name": "Some Event Date",
"children": [
{
"name": "2008",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 451,
"children": null
},
{
"name": "2009",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 407,
"children": null
},
{
"name": "2010",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 426,
"children": null
}
]
}]
}
]
}
]
};
//aggregate data to be nested under incident
vm.newChildData = [
{
"name": "Incident Date",
"children": [
{
"name": "2008",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 451,
"children": null
},
{
"name": "2009",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 407,
"children": null
},
{
"name": "2010",
"documentType": "Incident Date",
"aggregateUponField": "dateincidentstart",
"parent": "",
"count": 426,
"children": null
}
]
}
];
var loadData = function () {
//stip out array
var children = vm.treeData.children;
//search array for matching parent
$log.info(vm.lastNodeSelected);
var cnt = children.length;
for (var i = 0; i < cnt; i++) {
if (children[i].children) {
var innerCnt = children[i].children.length;
for (var c = 0; c < innerCnt; c++) {
if (children[i].children[c].name === vm.lastNodeSelected) {
children[i].children[c].children = vm.newChildData;
}
}
}
}
//wrap back in object and assign to ngModel
vm.updatedList = { children };
// $log.info(updatedList);
vm.treeData2 = vm.updatedList;
$timeout(function() {
$scope.$apply(function() {
vm.treeData = vm.updatedList;
})} , 0);
}
vm.getAggregateInfo = function (node) {
vm.lastNodeSelected = node.name;
loadData();
// $log.info(vm.lastNodeSelected);
};
}
})();
以下是treeview指令。
angular.module('app')
.directive('tree', function () {
return {
restrict: 'E',
replace: true,
scope: {
t: '=src',
filter: '&'
},
template: '<ul><branch ng-repeat="c in t.children track by $index" src="c" filter="filter({ object: object, isSelected: isSelected })"></branch></ul>'
};
});
angular.module('app')
.directive('branch', function ($compile) {
return {
restrict: 'E',
replace: true,
scope: {
b: '=src',
filter: '&',
checked: '=ngModel'
},
template: '<li class="dir-tree"><input type="checkbox" ng-click="innerCall()" ng-model="b.$$hashKey" ng-change="stateChanged(b.$$hashKey)" />{{ b.name }} <span ng-hide="visible"> ({{ b.count }})</span></li>',
link: function (scope, element, attrs) {
var clicked = '';
var hasChildren = angular.isArray(scope.b.children);
scope.visible = hasChildren;
if (hasChildren) {
element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');
$compile(element.contents())(scope);
}
element.on('click', function (event) {
event.stopPropagation();
if (hasChildren) {
element.toggleClass('collapsed');
}
});
scope.stateChanged = function (b) {
clicked = b;
};
scope.innerCall = function () {
scope.filter({ object: scope.b, isSelected: clicked });
};
}
};
});
我所看到的是当我点击事件复选框时,javascript对象确实更新了。您可以在输出中看到这个,以及选中复选框后绑定的第二个树视图。
我怀疑该问题与事件的$ digest周期有关,并且没有通知树实际更新。我已经尝试过,你可以在控制器中看到使用$scope.$apply()
包裹在超时但是这没有用来更新原始树。
对数组更新执行类似.push()
的附加操作,但尝试将新对象插入现有数组似乎不起作用。
有关如何让树更新并反映子对象的任何建议吗?
答案 0 :(得分:0)
这是一个略微修改的Plunker,以突出显示(并部分修复)问题。
我在link
指令的branch
函数中添加了以下行:
scope.$watch('b', function (newvalue, oldvalue) {
if (!oldvalue.children && newvalue.children) {
scope.visible = true;
element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');
$compile(element.contents())(scope);
}
}, true);
当树结构更新时,不再调用link
函数。因此,如果要添加新的子项,则不会为Angular编译这些子项。