2

I have two nested directives for building a treeview in Angular:

Parent directive:

myApp.directive('nodes', function() {
    return {
        restrict: "E",
        replace: true,
        scope: {
            nodes: '='
        },
        template: "<ul><node ng-repeat='node in nodes' node='node'></node></ul>"

    }
});

Child directive:

myApp.directive('node', function($compile) {
        return {
            restrict: "E",
            replace: true,
            scope: {
                node: '='
            },
            template: "<li>{{node.ObjectName}}</li>",
            link: function(scope, element, attrs) {
                if (angular.isArray(scope.node.Children)) {

                    element.append("<nodes nodes='node.Children'></nodes>");

                    $compile('<nodes nodes="node.Children"></nodes>')(scope, function(cloned, scope) {

                        element.append(cloned);
                    });
                }
            }
        }
    });

The controller:

function myController($scope, DataService) {
        $scope.init = function() {

            DataService.getData(0, 0).then(function(data) {
                $scope.treeNodes = $.parseJSON(data.d);
            });
        }

        $scope.focusNode = function(prmNode) {
            console.log(prmNode);
        }

    }

HTML:

<div ng-app="testTree" ng-controller="myController">
        <div ng-init="init()">
            <nodes nodes='treeNodes'></nodes>
        </div>
    </div>

My question is how can I implement a click on the <li> which will call the "focusNode" function in the controller?

2
  • can you post html part? Commented Jan 13, 2014 at 10:24
  • @MaximShoustin, I add my HTML part. Commented Jan 13, 2014 at 12:21

2 Answers 2

1

You could pass in the function through an attribute.

Javascript

var myApp = angular.module('myApp', []);

myApp.directive('nodes', function() {
    return {
        restrict: "E",
        replace: true,
        scope: {
            nodes: '=',
            clickFn: '&'
        },
        template: "<ul><node ng-repeat='node in nodes' node='node' click-fn='clickFn()'></node></ul>"
    }
});


myApp.directive('node', function($compile) {
    return {
        restrict: "E",
        replace: true,
        scope: {
            node: '=',
            clickFn: '&'
        },
        template: "<li><span ng-click='clickFn()(node)'>{{node.ObjectName}}</span></li>",
        link: function(scope, element, attrs) {
            if (angular.isArray(scope.node.Children)) {

                element.append("<nodes nodes='node.Children' click-fn='clickFn()'></nodes>");

                $compile('<nodes nodes="node.Children" click-fn="clickFn()"></nodes>')(scope, function(cloned, scope) {

                    element.append(cloned);
                });
            }
        }
    }
});

function myController($scope) {
  $scope.focusNode = function(prmNode) {
      console.log(prmNode);
  }

  $scope.root = {
    ObjectName: 'Root',
    Children:[{
      ObjectName: 'A',
      Children: [{
        ObjectName: 'B'
      }, {
        ObjectName: 'C'
      }]
    }]
  };
}

HTML

<!DOCTYPE html>
<html>

  <head>
    <script data-require="angular.js@*" data-semver="1.2.8" src="http://code.angularjs.org/1.2.8/angular.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app='myApp' ng-controller="myController">
    <node node="root" click-fn="focusNode"></node>
  </body>

</html>
Sign up to request clarification or add additional context in comments.

5 Comments

I'm getting an error: "Object #<Object> has no method 'on'". The error comes from this line: <span ng-click="clickFn()(node)" class="ng-binding">
Does this plunkr work for you? plnkr.co/edit/XvqTfoullnXDVWRqFIyw?p=preview
It doesn't show an error but it doesn't write to console when I click on the span.
Weird. What OS/browser are you using? Works on my Mac Maverick and Windows Server 2008 R2 on Chrome. i.imgur.com/YWJmQ6t.png
The error was gone after updating from jQuery 1.4.4 to 1.7+. Thanks.
1

Since I can't comment until I get 50 rep cred :(...

I just wanted to add that I also got an error when trying the plunkr that W.L.Jared shared above. To fix the error, I changed the controller from a global function to:

angular.module('myApp').controller('myController', function($scope){...})

The error went away.

Good answer though :) Exactly what I was looking for.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.