简体   繁体   中英

Angular Directive — Can't access child or grandchild nodes in a tree view

I have a directive that builds a tree view. It's based off of a code example at http://jsfiddle.net/KNM4q/113/ . I would like to be able to click on any node in the tree, and have the click execute a method in a controller that processes data particular to that node. While I have gotten the code working in the root node and the child nodes I can't make it work with grandchildren or great granchildren nodes.

Here is the plunker:

http://plnkr.co/edit/AKiD8ZyKK8dUSPEcWI3p?p=preview .

Here is the HTML:

<div ng-controller="appCtrl">

  <tree val="treeData" zo="itemDetail(param)"  ></tree>

</div>

Here is the directive:

angular.module('components')
    .directive('tree', function ($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: { val: '=', parentData:'=', zo:'&' },
        link: function (scope, element, attrs) {
            var template = '<span>{{val.text}}</span><button  ng-click="showDetail()"  ng-show="val.text">Show Detail</button> ';
            if (angular.isArray(scope.val.items)) {
                template += '<ul class="indent"><li ng-repeat="item in val.items"><tree val="item" parent-data="val.items" zo=zo({param:item.text})   >  </tree></li></ul>';
            }
            scope.showDetail = function(index) { 
                var param = 'aaa';
                scope.zo(); 

            };
            var newElement = angular.element(template);
            $compile(newElement)(scope);
            element.replaceWith(newElement);            
        }


    }
});

Here is the controller:

function appCtrl($scope) {
    var treeData = {
        "text": "root",
        "items": [{
            "text": "Furniture",
                "items": [{
                "text": "Tables & Chairs"
            }, {
                "text": "Sofas",
                    "items": [{
                    "text": "Tables & Chairs"
                }, {
                    "text": "Sofas"
                }]
            }, {
                "text": "Occasional Furniture"
            }]
        }, {
            "text": "Decor",
                "items": [{
                "text": "Bed Linen"
            }, {
                "text": "Curtains & Blinds"
            }, {
                "text": "Carpets"
            }]
        }]
    };

    //initial parameter that is sent
    $scope.param = 'root';

    $scope.treeData = treeData;

    $scope.itemDetail = function (param){
        alert('in controller ' + param);
    }
}

You want to pass the function as an object reference and 2 way bind it back to each parent level using = not & in directive scope.

HTML

<!-- notice removed "()" -->
<tree val="treeData" zo="itemDetail"  ></tree>

JS

Since zo is bound to parent scope function, can use it in template html

.directive('tree', function ($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: { val: '=', parentData:'=', zo:'=' },
        link: function (scope, element, attrs) {
            var template = '<span>{{val.text}}</span><button  ng-click="zo(val.text)"  ng-show="val.text">Show Detail</button> ';
            if (angular.isArray(scope.val.items)) {
                template += '<ul class="indent"><li ng-repeat="item in val.items"><tree val="item" parent-data="val.items" zo="zo"   >  </tree></li></ul>';
            }

            var newElement = angular.element(template);
            $compile(newElement)(scope);
            element.replaceWith(newElement);            
        }


    }

In simpler terms this is the same as doing:

function foo( param ){
   alert(param);
}

var bar = foo;

bar('someString') // alerts "someString"

DEMO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM