javascript - Update an angular treeview directive when a new object is added to the collection -
i have treeview directive credit http://codepen.io/bachly/pen/kwwrzg being starting block. trying update when add objects collection. can update object , insert new objects treeview directive never called once $scoped
item updated. data used come service @ point testing mock data.
the original collection looks this
$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: " new event", children: [ { name: "2010", filtertype: '_eventstartdate', parent: '_event' }, { name: "2011", filtertype: '_eventstartdate', parent: '_event' } ] } ] }] };
this generates tree view checkboxes using following directive , html
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 $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 }); }; } }; });
and html
<div ng-controller="treecontroller"> <tree src="mylist" iobj="object" filter="dosomething(object, isselected)"></tree> <a ng-click="clicked()"> link</a> </div>
when checkbox clicked new collection added existing 1 using lodashjs
ng-click event
$scope.dosomething = function (object, isselected) { if (isselected) { var item = object; console.log(item); nestassociation(object, $scope.mylist, theothercollection); } }
which creates new array , adds within children array
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); }
i can see in output have new object can't treeview update. have tried within directive add $compile(element) on click event in directive since array not built yet nothing changes.
do need add $watch directive , if or there other way can directive re-render , display new nested collection?
update
base on of feedback , questions here little more detail around question. issue seeing not in directive far moving data around issue cannot treeview re-render once array added existing model. following link is working plunker shows project works. running chrome dev tools can see in output model updated after checkbox selected
while see object updated, directive never updates show new array added object. part need understanding.
thanks in advance
you pass function inner directives (which best practice), have access scope.filter
. not dosomethingfunction
. 1 undefined
there.
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 $index" src="c" filter="filter(object, isselected)"> </branch> </ul>' }; });
next :
you can never access $$
variables in angularjs, because private. maybe should make 1 db..., $$hashkey
seems easy solution though.
checked
attribute might throw error, because ngmodel
not exist on tree directive template. (put @ least ?
before)
a checkbox can not have model $$hashkey.
ng-change , ng-click called @ same time, use simplest one.
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 }); } }; } }; });
update
you have same treecontroller
in tree
directive , in index.html
view. this causes view not update!
i deleted 1 in directive, otherwise you'll have controller each child.
saw console.log message in controller, in controller 1 directive.
not accessing controller of index.html
.
then fixed filter
function communication between childs :
you forgot communicate filter function when append new tree
's :
element.append('<tree src="b" filter="filter({ object: object, isselected: isselected })"></tree>');
also, in parent directive template, need hash send parameters function :
filter="filter({ object: object, isselected: isselected })"
i edited plunker here without changing code above comments made.
(i'm not sure write not want , because did not comment rather not change still undertand code fast)
view updating now!
think little debug want , comments above should enough.
edit 2
forgot return object property chrilden
. returned array, caused problem.
function updatemylist(data) { var transformed = { children : data }; $scope.mylist = transformed; }
here working plunker.
Comments
Post a Comment