AngularJS pass parameters in directive template to controller

13,603

Solution 1

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.

Solution 2

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.

Share:
13,603

Related videos on Youtube

brabertaser19
Author by

brabertaser19

Updated on June 04, 2022

Comments

  • brabertaser19
    brabertaser19 almost 2 years

    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?

    • Ivan Chernykh
      Ivan Chernykh over 9 years
      It will be easier to help you (and to get the bounty) if you will create a jsfiddle or plnkr for us, please
    • brabertaser19
      brabertaser19 over 9 years
      @Cherniv hm, i didn' know how to add ui bootstrap... embed.plnkr.co/LlzPgsWrwcYd59sa2wxd/preview
    • Pankaj Parkar
      Pankaj Parkar over 9 years
      while compiling DOM, why do you need $scope.$new() inside isolated scope?
    • brabertaser19
      brabertaser19 over 9 years
      @pankajparkar to render childs of childs
  • brabertaser19
    brabertaser19 over 9 years
    take a look at my example, i didn't know how to implement it there
  • brabertaser19
    brabertaser19 over 9 years
    i need to pass data from note which is currently clicked to controller wthis is not in directive