我一直在尝试每一个可以想象的组合,试图让树形菜单的分支在树结构发生变化时正确刷新。基本上我所拥有的是一组递归嵌套指令来显示树的分支。我构建了一个javascript类来存储树结构的任何给定部分的指令数据。 该类拥有一个我基本上接口的模型,因此它有一些已知的方法(例如getVals()从ajax和getId(),getName(),getLabel()来加载数据以检索构建树的公共属性) 。然后我以两种方式使用它来构建具有此对象对的树,第一种是针对给定的分支点,它将包含描述“组”的单个模型(具有多个子分支)(从Doctrine ORM集合加载数据)这基本上是一个学说实体样式对象的数组),另一个是表示实际分支的实体的单个模型。 这个想法是任何主干(分支点)都有两个选项 - 一个用于显示该组/父级的详细信息,另一个用于显示子项的名称。然后每个孩子都可以选择显示它的详细信息或显示它的孩子等等。
function treeBranch() {
this.refresh = false;
// class and title information for expander button
this.toggleShown = function() {
this.vis = !(this.vis);
if(this.vis == true) {
this.trunkClass = 'glyphicon glyphicon-chevron-down';
this.trunkTitle = 'collapse';
} else {
this.trunkClass = 'glyphicon glyphicon-chevron-right';
this.trunkTitle = 'expand';
}
};
// default populator code
this.populate = function(toggle,force,pcbf) {
toggle = (typeof(toggle) == 'boolean') ? toggle : true;
force = (typeof(force) == 'force') ? force : false;
var br = this;
if((typeof(br.subBranches) == 'undefined') || (br.subBranches.length == 0))
force = true;
if((typeof(br.model) != 'undefined') && (typeof(br.loadMethod) != 'undefined')) {
br.model[br.loadMethod](
function() {
br.subBranches = []; // reset subBranches array
for(var k in br.model.subs) { // subs should be loaded with a keyed array
var newSubBranch = new treeBranch();
newSubBranch.model = br.model.subs[k];
newSubBranch.label = 'Name: ' + newSubBranch.model.getName(); // expects model to have a getName method
newSubBranch.trunk = br;
br.subBranches.push(newSubBranch);
}
(toggle == true) && br.toggleShown();
(typeof(pcbf) == 'function') && pcbf();
},
force,
br.model.getFilter()
);
}
};
this.getLabel = function() {
if(this.model != null) {
return ((typeof(this.model.getId) == 'function') ? this.model.getId() : '') +
((typeof(this.model.getName) == 'function') ? ' '+this.model.getName() : '');
} else {
return this.label;
}
}
// core properties
this.label = '';
this.vis = false;
this.trunkClass = 'glyphicon glyphicon-chevron-right';
this.trunkTitle = 'expand';
this.subBranches = [];
this.trunk = null;
this.model = null;
this.loadMethod = 'getVals'; // function of model to populate it with data
};
/**
-Trunk {treeBranch with entity as model}
[show details option]
+--> branches {treeBranch instance with collection as model}
[show branches/children option]
- branch1 {treeBranch entity model}
[show details option]
+--> branches {treeBranch collection model}
[show branches/children option]
- subbranch1 ... etc
- branch2 {treeBranch with entity as model}
[show details option]
+--> branches {treeBranch collection model}
[show branches/children option]
... etc ...
*/
当我开始添加函数来操纵给定分支点(实体)的属性和/或添加/删除/移动分支本身时,我的问题就出现了。我有用于添加/更新/删除的表单(仍然在移动中工作)但是当保存数据时,因为我的模型正在执行他们自己的ajax rest调用,所以树不会更新以反映更改。 其中一个问题是我在孩子的UL标签之后设置了添加按钮 - 我可以更新,因为它与带有UL标签的模板在同一指令中。但是这些孩子处于第二个指令之下,该指令与LI周围的ng-repeat相关联,用于显示每个子分支包装器。因此,更新/删除按钮显示在该模板中,但我需要刷新的范围是父级。 我知道我可以使用$ parent。$ parent.reload()来调用我的刷新脚本,但是当我开始执行'move'功能时,我可能会在树中间移动一个列表项。 我在模板的分支点有一个“刷新”按钮,并尝试做一个document.getElementById('branchpointX')。click();但这很狡猾,而且我一直在试图找出在该范围的.reload()函数中刷新范围的最佳方法。 $ scope。$ apply有时会与现有的$ digest刷新冲突,甚至将它们抛入$ timeout有时仍然会抛出一个刷新已经在进行中的错误。
所以我想知道在所述指令的层次结构树中刷新特定指令的最佳方法是什么?我已经尝试在每个subBranch中构建一个堆栈,其分支点的标签返回原点,但是如果我尝试运行treeStack ['someParentId']。reload()它在子范围内似乎不起作用
SW
答案 0 :(得分:0)
文字过多。
所以,这是简单的树指令
JSON:
var youList = [
{'display': 'parent 1', 'description': 'parent 1 desc', 'children': [
{'display': 'parent 1 child 1', 'description': 'parent 1 desc child 1', 'children': [
{'display': 'parent 1 child 1 sub-child 1', 'description': 'parent 1 desc child 1 sub-child 1', 'children': []},
{'display': 'parent 1 child 1 sub-child 2', 'description': 'parent 1 desc child 1 sub-child 2', 'children': []}
]},
{'display': 'parent 1 child 2', 'description': 'parent 1 desc child 2', 'children': []}
]},
{'display': 'parent 2', 'description': 'parent 2 desc', 'children': [
{'display': 'parent 2 child 1', 'description': 'parent 2 desc child 1', 'children': []},
{'display': 'parent 2 child 2', 'description': 'parent 2 desc child 2', 'children': []}
]}
];
HTML:
<my-tree parent-list="youList"></my-tree>
指令:
.directive('myTree', function ($compile) {
return {
restrict: 'E',
link: function (scope, element, attrs) {
var parentList = attrs.parentList;
var template =
'<ul>' +
' <li class="" ng-repeat="item in ' + parentList + '">' +
' <label>{{item.display}}</label> : <small>{{item.description}}</small>' +
' <my-tree parent-list="item.children" ng-if="item.children && item.children.length > 0"></my-tree>' +
' </li>' +
'</ul>';
element.html('').append($compile(template)(scope));
}
}
})
添加/删除必要的按钮以使用&#39; yourList&#39;进行操作。变量。 通过更新&#39; yourList&#39;的任何部分,您的树结构将得到更新。
应该很容易。不需要技能:))
答案 1 :(得分:0)
原来我想要的是使用rootScope设置$ broadcast触发器,然后我可以使用$ on和每个相应范围内的回调函数来监听。
e.g。保存,当被调用时有一个回调函数,所以我的编辑指令(在不同的工厂控制器中)可以添加$ rootScope。$ broadcast('branch1Reload');回调,然后该分支的指令只需要一个$ rootscope。$ on('branch1Reload',function(){/ * do stuff * /; scope.reload();});