【问题标题】:AngularJS pass parameters in directive template to controllerAngularJS将指令模板中的参数传递给控制器
【发布时间】:2015-01-01 08:05:31
【问题描述】:

在我的应用程序中,我有这样的指令:

.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) {}

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

【问题讨论】:

  • 如果您为我们创建一个 jsfiddle 或 plnkr,会更容易帮助您(并获得赏金)
  • @Cherniv hm,我不知道如何添加 ui 引导程序...embed.plnkr.co/LlzPgsWrwcYd59sa2wxd/preview
  • 在编译 DOM 时,为什么需要在隔离范围内使用 $scope.$new()?
  • @pankajparkar 渲染孩子的孩子

标签: angularjs angularjs-directive directive


【解决方案1】:

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

在您的 nodeList 指令中,像这样调用您的 node

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

在你的 node 指令中,像这样调用你的 nodeList

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

所以引用“node_item”在孩子的孩子之间正确传递......到最顶层的父母(你的控制器:)

看看这个:Plunker

原因:

您的 有自己的范围,您需要将“node_item”传递给父范围(您的控制器),很简单!棘手的部分是该函数是在孙作用域()内调用的,因此您需要再次将“node_item”从孙作用域传递给子作用域。

您也不需要在调用 compile 时创建新范围。您拥有的 $scope 对象也是父范围的 new 范围。

【讨论】:

    【解决方案2】:

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

       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);
             }
           }
         };
       });
      div {
        margin-left: 20px;
      }
    <!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>

    【讨论】:

      【解决方案3】:

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

      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

      【讨论】:

      • 看看我的例子,我不知道如何实现它
      • 我需要将当前点击的笔记中的数据传递给控制器​​,而这不在指令中
      【解决方案4】:

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

      我没有可用的代码,但这个概念可以工作。

      【讨论】:

        猜你喜欢
        • 2018-12-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多