AngularJS将指令模板中的参数传递给控制器

时间:2014-11-05 07:45:20

标签: angularjs angularjs-directive directive

在我的应用中,我有这样的指示:

.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());
        }
    };
})

和这样的html:

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

并在控制器中:

$scope.editArticle = function(vArticle) {}

当我只有一个指令 - 一切都很清楚,但是当我的指令调用另一个指令时如何传递参数?这是真的吗?怎么样?

4 个答案:

答案 0 :(得分:3)

您只需要更改一小段代码,以便函数调用正确接收参数

nodeList 指令中,按照以下方式调用节点

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

并在您的节点指令中,像这样调用 nodeList

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

所以参考&#34; node_item&#34;在孩子的孩子的孩子中正确地传递给最顶级的父母(你的控制者:)

看看这个:Plunker

原因:

您的&lt; node-list&gt; 有自己的范围,您需要传递&#34; node_item&#34;到父范围(你的控制器),简单!棘手的部分是在孙子范围内调用该函数(&lt; node&gt; ),因此您再次需要传递&#34; node_item&#34;从孙子到孩子。

您还 需要在调用compile时创建新范围。你在那里的$ scope对象还有一个来自父范围的 new 范围。

答案 1 :(得分:2)

您可以使用控制器在指令之间进行通信,并使此依赖项显式化。一个简单的例子:

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;
      }
    }
  })

这里,指令bar声明对指令foo的依赖作为封闭指令。因此,指令可以在链接函数传递另一个参数时进行通信。因此,此剪辑的HTML将显示something

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

你可以play with this example in this JSFiddle

答案 2 :(得分:0)

NodeList指令

从您的子节点指令可以调用的nodeList指令中公开控制器API,以删除或编辑文章。

controller: function ($scope) {
    this.deleteArticle = function (node) {
        var index = $scope.nodes.indexOf(node);
        if (index >= 0) {
            $scope.nodes.splice(index, 1);
            $scope.$emit('articleDeleted', node);
        }

    }
    this.editArticle = function (node) {
        var index = $scope.nodes.indexOf(node);
        if (index >= 0) {
            $scope.$emit('articleEdited', node);
        }

    }
}

节点指令

在node指令中,手动编译nodeList指令以避免递归,并添加链接以调用nodeList控制器的API:

link: function ($scope, $element, $attrs, nodeListController) {
    var template = angular.element('<node-list ng-model="node.nodes" ng-hide="node.hidden"></node-list>');
     $element.append(template);
     $compile(template)($scope);

      $scope.delete = function (node) {
          nodeListController.deleteArticle(node);
      }

      $scope.edit = function (node) {
          nodeListController.editArticle(node);
      }
}

家长控制器:

使用$emit通知用户您的指令已编辑或删除节点。

$scope.$on('articleEdited', function (evt, node) {
    alert('Edited ' + node.Title);
});
$scope.$on('articleDeleted', function (evt, node) {
    alert('Deleted ' + node.Title);
});

&#13;
&#13;
   var app = angular.module('app', []);
   var ctrl = app.controller('ctrl', function($scope, $rootScope) {
     $scope.nodes = [{
       Title: 'Title 1',
       nodes: [{
         Title: 'Title 1.1',
         nodes: []
       }, {
         Title: 'Title 1.2',
         nodes: []
       }]
     }, {
       Title: 'Title 2',
       nodes: [{
         Title: 'Title 2.1',
         nodes: [{
           Title: 'Title 2.1.1',
           nodes: []
         }, {
           Title: 'Title 2.1.2',
           nodes: []
         }]
       }, {
         Title: 'Title 2.2',
         nodes: [{
           Title: 'Title 2.2.1',
           nodes: []
         }, {
           Title: 'Title 2.2.2',
           nodes: []
         }, {
           Title: 'Title 2.2.3',
           nodes: []
         }, {
           Title: 'Title 2.2.4',
           nodes: []
         }]
       }]
     }];
     $scope.$on('articleEdited', function(evt, node) {
       alert('Edited ' + node.Title);
     });
     $scope.$on('articleDeleted', function(evt, node) {
       alert('Deleted ' + node.Title);
     });


   });
   app.directive('nodeList', function($parse) {
     return {
       restrict: 'E',
       scope: {
         nodes: '=ngModel'
       },
       template: '<div close-others="true"><node ng-repeat="item in nodes" ng-model="item" ></node></div>',
       controller: function($scope) {
         this.deleteArticle = function(node) {
           var index = $scope.nodes.indexOf(node);
           if (index >= 0) {
             $scope.nodes.splice(index, 1);
             $scope.$emit('articleDeleted', node);
           }

         }
         this.editArticle = function(node) {

           var index = $scope.nodes.indexOf(node);
           if (index >= 0) {
             $scope.$emit('articleEdited', node);
           }

         }
       },
       link: function($scope, $element, $attrs) {}
     };
   });

   app.directive('node', function($compile) {
     return {
       restrict: 'E',
       require: '^nodeList',
       scope: {
         node: '=ngModel'
       },
       controller: function($scope) {

       },
       template: '<div><span ng-click="node.hidden = !node.hidden">{{node.Title}}</span><a href="#" ng-click="edit(node)">Edit</a> <a href="#" ng-click="delete(node)">Delete</a></div>',
       link: function($scope, $element, $attrs, nodeListController) {
         var template = angular.element('<node-list ng-model="node.nodes" ng-hide="node.hidden"></node-list>');
         $element.append(template);
         $compile(template)($scope);

         $scope.delete = function(node) {
           nodeListController.deleteArticle(node);
         }

         $scope.edit = function(node) {
           nodeListController.editArticle(node);
         }
       }
     };
   });
&#13;
  div {
    margin-left: 20px;
  }
&#13;
<!DOCTYPE html>
<html>

<head>
  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>

<body ng-app="app" ng-controller="ctrl">
  <node-list ng-model="nodes">
  </node-list>
</body>

</html>
&#13;
&#13;
&#13;

答案 3 :(得分:-1)

您可以使用服务传递您使用的任何参数 您需要添加触发器以在创建指令时获取信息 此触发器应从服务获取信息并使用它 如果它被创建并获得一个未定义的参数,那么它将是第一个指令

我没有工作代码,但这个概念可行。