草庐IT

javascript - 将新对象添加到集合时更新 Angular TreeView 指令

coder 2024-07-16 原文

我有一个 treeview 指令归功于 http://codepen.io/bachly/pen/KwWrzG作为我的起点。当我将对象添加到集合中时,我正在尝试更新。我可以更新对象并插入新对象,但是一旦更新了 $scoped 项目,就永远不会调用 treeview 指令。 最终,使用的数据将来自服务,此时我只是使用模拟数据进行测试。

原始集合是这样的

$scope.myList = {
            children: [
              {
                  name: "Event",
                  children: [
                    {
                        name: "Event Date",
                        parent:"Event",
                        children: [
                          {
                              name: "2008",
                              filterType: '_eventStartDate',
                              parent: 'Event'
                          },
                          {
                              name: "2009",
                              filterType: '_eventStartDate',
                              parent: 'Event'
                          }
                        ]
                    },
                    {
                        name: "Event Attendee",
                        parent: "Event",
                        children: [
                          {
                              name: "Person 1",
                              filterType: '_eventAttenddeeName',
                              parent: 'Event Attendee'
                          },
                          {
                              name: "Person 2",
                              filterType: '_eventAttenddeeName',
                              parent: 'Event Attendee'
                          }
                        ]
                    }
                  ]
              }]
   };


   var TheOtherCollection = {
       children: [
         {
             name: "A New Event",
             children: [
               {
                   name: "The Other Date",
                   parent: " A New Event",
                   children: [
                     {
                         name: "2010",
                         FilterType: '_eventStartDate',
                         Parent: '_event'
                     },
                     {
                         name: "2011",
                         FilterType: '_eventStartDate',
                         Parent: '_event'
                     }
                   ]
               }
             ]
         }]
   };

这会使用以下指令和 html 生成带有复选框的 TreeView

app.directive('tree', function () {
    return {
        restrict: 'E', 
        replace: true,
        scope: {
            t: '=src',
            filter: '&'
        },
        controller: 'treeController',
        template: '<ul><branch ng-repeat="c in t.children track by $index"  src="c" filter="doSomething(object, isSelected)"></branch></ul>'
    };
});

app.directive('branch', function($compile) {

    return {
        restrict: 'E', 
        replace: true, 
        scope: {
            b: '=src',
            filter: '&',
            checked: '=ngModel'
        },

            template: '<li><input type="checkbox" ng-click="innerCall()" ng-model="b.$$hashKey" ng-change="stateChanged(b.$$hashKey)" ng-hide="visible" /><a>{{ b.name }}</a></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"></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 });
                };
            }
        };
    });

然后是html

  <div ng-controller="treeController">
        <tree src="myList" iobj="object" filter="doSomething(object, isSelected)"></tree>

        <a ng-click="clicked()"> link</a>
    </div>

单击复选框时,使用 lodashjs 将新集合添加到现有集合

ng-点击事件

$scope.doSomething = function (object, isSelected) {
    if (isSelected) {
        var item = object;
        console.log(item);
        nestAssociation(object, $scope.myList, TheOtherCollection);
    }
}

创建新数组并将其添加到子数组中

function nestAssociation(node, oldCollection, newAggregates) {
    // var item = fn(oldCollection, node.parent);
    var updatedArray = _.concat(oldCollection.children, newAggregates);
    console.log(updatedArray);
    if (updatedArray != null)
        updateMyList(updatedArray);
}

我可以在输出中看到我有一个新对象,但我无法更新 TreeView 。我已经尝试在指令中在指令中的 click 事件上添加一个 $compile(element) 但由于数组尚未构建,因此没有任何变化。

我是否需要向该指令添加一个 $watch?如果需要,我可以从何处获取指令以重新呈现并显示新的嵌套集合?

更新

根据此处的一些反馈和问题,围绕该问题提供了更多详细信息。我看到的问题不在指令中,就围绕问题移动数据而言,一旦将数组添加到现有模型,我就无法让 TreeView 重新呈现。 以下链接is a working plunker这显示了项目当前的工作情况。 运行 chrome 开发工具我可以在输出中看到模型在选中复选框后更新

虽然我看到对象已更新,但指令从未更新以显示添加到对象的新数组。这是我需要帮助理解的部分。

提前致谢

最佳答案

您将函数传递给内部指令(这是最佳实践),但您可以访问 scope.filter .不是doSomethingFunction .这个是undefined那里。

filter="doSomething(object, isSelected)"
=>
filter="filter(object, isSelected)"

app.directive('tree', function () {
    return {
        restrict: 'E', 
        replace: true,
        scope: {
            t: '=src',
            filter: '&'
        },
        controller: 'treeController',
        template: '<ul>  
                    <branch ng-repeat="c in t.children track by $index"       
                   src="c" filter="filter(object, isSelected)">  
                    </branch>  
                  </ul>'
    };
});

下一个:

您永远无法访问 $$ angularJS 中的变量,因为它们是私有(private)的。也许你应该从你的数据库中制作一个...,但是 $$hashkey不过,这似乎是一个简单的解决方案。

checked属性可能会引发错误,因为 ngModel您的树指令模板中不存在。 (在前面至少放一个?)

复选框不能有 $$hashkey 作为模型。
ng-change 和 ng-click 总是会同时被调用,使用最简单的一个。

app.directive('branch', function($compile) {

    return {
        restrict: 'E', 
        replace: true, 
        scope: {
            b: '=src',
            filter: '&'
        },

            template: '<li><input type="checkbox" ng-click="innerCall(b.$$hashKey)" ng-model="isChecked" ng-hide="visible" /><a>{{ b.name }}</a></li>',
            link: function (scope, element, attrs) {

               scope.isChecked = false;
               var hasChildren = angular.isArray(scope.b.children);
                scope.visible = hasChildren;
                if (hasChildren) {
                    element.append('<tree src="b"></tree>');
                    $compile(element.contents())(scope);
                }
                element.on('click', function(event) {
                    event.stopPropagation();
                    if (hasChildren) {
                        element.toggleClass('collapsed');
                    }
                });

                scope.innerCall = function(hash) {
                    if(scope.isChecked){
                       scope.filter({ object: scope.b, isSelected: hash });
                    }

                };
            }
        };
    });

更新

你有相同的treeController在你的tree指令和你的 index.html看法。 这就是导致 View 不更新的原因!

我在你的指令中删除了那个,否则你会为每个 child 都有一个 Controller 。
您在 Controller 中看到了良好的 console.log 消息,但它在一个 Controller 中用于 ONE 指令。
您没有访问 index.html 的 Controller .

然后我修复了 filter child 之间的功能交流:

当你追加新的tree时,你忘了传达过滤功能的:

element.append('<tree src="b" filter="filter({ object: object, isSelected: isSelected })"></tree>');

此外,在您的父指令模板中,您还需要散列来向函数发送参数:
filter="filter({ object: object, isSelected: isSelected })"

我编辑了你的 Plunker HERE无需使用我所做的上述评论更改代码。
(我不确定你写的是不是你想要的,因为你没有评论我宁愿不改变它所以你仍然可以快速理解你的代码)
但是 View 现在正在更新!
我认为根据您的需要进行一些调试,上面的评论就足够了。

编辑 2
您忘记返回属性为 chrilden 的对象.您返回了一个数组,这导致了问题。

function updateMyList(data) {
      var transformed = { children : data };
        $scope.myList = transformed;
    }

这是一个有效的 PLUNKER .

关于javascript - 将新对象添加到集合时更新 Angular TreeView 指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35232872/

有关javascript - 将新对象添加到集合时更新 Angular TreeView 指令的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 我需要将 Bundler 本身添加到 Gemfile 中吗? - 2

    当我使用Bundler时,是否需要在我的Gemfile中将其列为依赖项?毕竟,我的代码中有些地方需要它。例如,当我进行Bundler设置时:require"bundler/setup" 最佳答案 没有。您可以尝试,但首先您必须用鞋带将自己抬离地面。 关于ruby-我需要将Bundler本身添加到Gemfile中吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/4758609/

  3. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  4. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  5. ruby - 将 Bootstrap Less 添加到 Sinatra - 2

    我有一个ModularSinatra应用程序,我正在尝试将Bootstrap添加到应用程序中。get'/bootstrap/application.css'doless:"bootstrap/bootstrap"end我在views/bootstrap中有所有less文件,包括bootstrap.less。我收到这个错误:Less::ParseErrorat/bootstrap/application.css'reset.less'wasn'tfound.Bootstrap.less的第一行是://CSSReset@import"reset.less";我尝试了所有不同的路径格式,但它

  6. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  7. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  8. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  9. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  10. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

随机推荐