0

我一直在拉我的头发,尝试每个可想象的组合,试图在树结构发生更改时正确地刷新树菜单的分支。基本上我所拥有的是一组递归嵌套指令来显示树的分支。我构建了一个JavaScript类来存储树结构的任何给定部分的指令数据。 该类拥有一个模型,我本质上接口,所以它有一些已知的方法(例如getVals()从ajax加载数据和getId(),getName(),getLabel()检索建立树的公共属性)。然后我以两种方式使用它来构建具有此对象对的树,第一个对于给定的分支点,它将包含描述“组”(使用从Doctrine ORM集合加载的数据的单个模型(具有多个子分支)基本上是一个主体实体样式对象的数组),另一个是表示实际分支的实体的单个模型。 想法是任何树干(分支点)将有两个选项 - 一个显示该组/父母的详细信息,另一个显示子女的名字。然后,每个小孩都可以选择显示细节或显示孩子等等。刷新angularjs中的特定指令

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休息调用,所以树不会更新以反映更改。 其中一个问题是,我在儿童的UL标签后面设置了添加按钮 - 这样我就可以更新,因为它与具有UL标签的模板具有相同的指令。但是孩子们正处在第二个指令中,这个指令与L1周围的ng-repeat关联起来以显示每个子分支包装器。因此更新/删除按钮显示在该模板中,但我需要刷新的范围是父级。 我知道我可以做$ parent。$ parent.reload()来调用我的刷新脚本,但是当我开始做'移动'功能时,我可能会在树的中间移动一个列表项。 我在模板中的分支点有一个“刷新”按钮,并试图做一个document.getElementById('branchpointX')。click();但是这是一个笨拙的问题,我一直试图找出在该范围的.reload()函数中刷新该范围的最佳方法。 $ scope。$ apply有时会与现有的$ digest刷新冲突,甚至在$ timeout中抛出它们有时仍然会抛出一个刷新错误。

所以我想知道什么是最好的方法来刷新所述指令的叶状树中的特定指令?我已经尝试在每个subBranch中构建一个带有分支点标签的栈,但是如果我尝试运行treeStack ['someParentId']。reload()它在子范围中似乎不起作用。

SW

回答

0

原来我在找的是使用rootScope设置$广播触发器,然后我可以使用$ on和每个范围内的回调函数来侦听。

例如保存,当被调用时有一个回调函数,所以我的编辑指令(在不同的工厂控制器中)可以添加$ rootScope。$ broadcast('branch1Reload');到回调,那么该分支的指令只需要一个$ rootcope。$ on('branch1Reload',function(){/ * do stuff * /; scope.reload();});

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)); 
     } 
    } 
}) 

添加必要的按钮添加/删除操作与' yourList'变量。 通过更新'yourList'的任何部分,您的树结构得到更新。

应该很容易。没有技能要求:)

+0

re:太多的文字。如果我少了,人们会问我包括更多的细节。太多的编辑评论来开始一个答案。 – Scott

+0

我认为你错过了关键的东西(那些“太多文本”中的项目之一) - 数据存储在独立的对象中,这些对象执行自己的ajax/populating/hydrating,并且角度在他们看不到它们时会改变在另一个指令,服务或工厂中被修改。 – Scott

+0

至少我试图帮助你:) –