Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS pass parameters in directive template to controller

In my app i have such directives:

.directive('nodeList', function($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: {
            nodes: '=ngModel',
            deleteArticle: '&',
            editArticle: '&'
        },
        link: function ($scope, $element, $attrs) {
            if (angular.isArray($scope.nodes)) {
                $element.append('<accordion close-others="true"><node ng-repeat="item in nodes" ng-model="item" delete-article="deleteArticle(node_item)" edit-article="editArticle(node_item)"></node></accordion>');
            } 
            $compile($element.contents())($scope.$new());
        }
    };
})

.directive('node', function($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: {
            node: '=ngModel',
            deleteArticle: '&',
            editArticle: '&'
        },
        link: function ($scope, $element, $attrs) {
            if (angular.isArray($scope.node.Options) && $scope.node.Options.length > 0) {
                $element.append('<accordion-group><accordion-heading>{{node.Title}}   <a href=\"javascript:void(0)\" ng-click=\"editArticle({node_item: node})\" data-toggle=\"modal\" data-target=\"#new-article\" class=\"action\"><i class=\"glyphicon glyphicon-edit\"></i></a></accordion-heading><node-list ng-model="node.Options"></node-list>{{node.Content}}</accordion-group>');
            } else {
                $element.append('<accordion-group><accordion-heading>{{node.Title}}   <a href=\"javascript:void(0)\" ng-click=\"editArticle({node_item: node})\" data-toggle=\"modal\" data-target=\"#new-article\" class=\"action\"><i class=\"glyphicon glyphicon-edit\"></i></a></accordion-heading>{{node.Content}}</accordion-group>');
            }
            $compile($element.contents())($scope.$new());
        }
    };
})

and such html:

<node-list ng-model="articles" delete-article="deleteArticle(node_item)" edit-article="editArticle(node_item)"></node-list>

and in controller:

$scope.editArticle = function(vArticle) {}

when i have only one directive - all is clear, but how to pass parameters when my directive is calling another directive? is it real? and how?

like image 765
brabertaser19 Avatar asked Nov 05 '14 07:11

brabertaser19


2 Answers

You just need to change a very small piece of you code in order for your function call to receive the argument correctly

in your nodeList directive, call to your node like this:

<node ng-repeat="item in nodes" ng-model="item" delete-article="deleteArticle({node_item: node_item})" edit-article="editArticle({node_item: node_item})"></node>

and in your node directive, call to your nodeList like this:

<node-list ng-model="node.Options" delete-article="deleteArticle({node_item: node_item})" edit-article="editArticle({node_item: node_item})"></node-list>

So the reference "node_item" being passed correctly amongst children of children of children... to the top most parent (your controller:)

Have a look at this: Plunker

The reason:

Your <node-list> has its own scope, you need to pass "node_item" to the parent scope (your controller), simple! The tricky part is that the function is being called inside a grandchild scope (the <node>), so you then again need to pass "node_item" from the grandchild to the child.

You also don't need to create a new scope when calling compile. The $scope object you have there was also a new scope from the parent scope.

like image 107
Mr. Duc Nguyen Avatar answered Nov 11 '22 04:11

Mr. Duc Nguyen


You can communicate between directives by using a controller and by making this dependency explicit. A simple example:

var myApp = angular.module('myApp', [])
  .directive('foo', function () {
    return {
      restrict: 'E',
      controller: function ($scope) {
        this.property = 'something';
      },
      link: function (scope, element) {
      }
    };
  })
  .directive('bar', function() {
    return {
      require: '^foo',
      link: function (scope, element, attrs, fooCtrl) {
          console.log(fooCtrl.property);
        scope.value = fooCtrl.property;
      }
    }
  })

Here, directive bar declares a dependency to directive foo as an enclosing directive. Therefore, the directives can communicate as the link function is passed an additional argument. This HTML snipped will therefore display something:

<div ng-app="myApp">
    <foo><bar>{{ value }}</bar></foo>
</div>

You can play with this example in this JSFiddle.

like image 2
Rafael Winterhalter Avatar answered Nov 11 '22 03:11

Rafael Winterhalter