从另一个指令中调用指令

时间:2015-12-18 15:16:36

标签: javascript html angularjs

请考虑tryout on Plunkr

我有一个简单的设置:

<body ng-app="myApp">
    <div ng-controller="myController">
      <parent-directive></parent-directive>
      <child-directive></child-directive>
    </div>
</body>

将父指令定义为:

app.directive("parentDirective", [
    "$compile",
    function (
        $compile) {
        return {
            scope: {
                person: "="
            },
            restrict: "E",
            template: "<h3>I'm a parent</h3>",
            controller: [
                "$scope",
                function ($scope) {
                    // --- PRIVATE --- //

                    var self = {};

                    $scope.ClickMe = function() {
                      alert('Parent clicked');
                    };
                }],
            link: function ($scope, $elem, $attrs) {
            }
        };
    }]);

并且子指令定义如下:

app.directive("childDirective", [
    "$compile",
    function (
        $compile) {
        return {
            scope: {
                person: "="
            },
            restrict: "E",
            require: "^?parentDirective",
            template: "<h3>I'm a child, click <button ng-click='ClickMe()'>here</button></h3>",
            controller: [
                "$scope",
                function ($scope) {
                    // --- PRIVATE --- //

                    var self = {};

                    $scope.ClickMe = function() {
                      alert('child clicked');
                      $scope.parentDirective.ClickMe();
                    };
                }],
            link: function ($scope, $elem, $attrs) {
            }
        };
    }]);

处理child点击,但是`parent&#39;上定义的点击返回undefined:

  

TypeError:无法读取属性&#39; ClickMe&#39;未定义的

看着控制台。

知道出了什么问题吗?

3 个答案:

答案 0 :(得分:1)

  

知道出了什么问题吗?

  1. 不能 require兄弟指令。
  2. 必需的指令控制器方法会自动暴露到您的示波器上。
  3. 您应该在控制器本身上公开方法,而不是在指定的$scope上公开。
  4. 您可以require在与父元素上的相同的元素上定义的指令。

    <child-directive parent-directive></child-directive>
    
    <parent-directive>
      <child-directive></child-directive>
    </parent-directive>
    

    当你require另一个指令的控制器(又称暴露的API)时,它并没有神奇地结束在require指令的$ scope上。

    但它最终会在link函数中作为第四个参数。

    像这样:

    .directive('child', function () {
      return {
        require: '?^parentDirective',
        link: function (scope, el, attrs, parentDirectiveController) {
          scope.clickMe = function () {
            parentDirectiveController.clickMe();
          };
        }
      };
    });
    

    将您希望在其他指令中使用的方法公开到this而不是$ scope,因为这样做的$ scope方式在您拥有隔离范围时不会像您希望的那样工作。

    .directive('parent', 
      controller: function () {
        this.clickMe = function () {};
      }
    }
    

    让你的榜样有效;

    <parent>
      <child></child>
    </parent>
    
    .directive('parent', function () {
      return {
        controller: function () {
          this.clickMe = function () {};
        }
      };
    }
    
    .directive('child', function () {
      return {
        require: '^?parent',
        link: function (scope, el, attrs, parentCtrl) {
          scope.clickMe = function () {
            parentCtrl.clickMe();
          };
        } 
      };
    }); 
    

    您的plunker的简化(和工作)版本:http://plnkr.co/edit/nao4EvbptQm7gDKkmZS2?p=preview

答案 1 :(得分:0)

将您的child指令放在父指令模板中。然后使用$ scope。$ parent.ClickMe()。这就是它的样子。

简单设置:

<body ng-app="myApp">
    <div ng-controller="myController">
        <parent-directive></parent-directive>
    </div>
</body> 

父指令:

app.directive("parentDirective", [
    function () {
        return {
            scope: {},
            restrict: "E",
            template: "<h3>I'm a parent</h3><child-directive></child-directive>",
            controller: [
                "$scope",
                function ($scope) {
                    $scope.ClickMe = function() {
                        alert('Parent clicked');
                    };
                }
            ]
        };
    }
]);

儿童指令:

app.directive("childDirective", [
    function () {
        return {
            restrict: "E",
            template: "<h3>I'm a child, click <button ng-click='ClickMe()'>here</button></h3>",
            controller: [
                "$scope",
                function ($scope) {
                    $scope.ClickMe = function() {
                        alert('child clicked');
                        $scope.$parent.ClickMe();
                    };
                }
            ]
        };
    }
]);

答案 2 :(得分:0)

我可能会稍微考虑一下你的问题,但我会看看$ broadcast。这个想法是你可以播放一个活动并且有&#34; n&#34;在您的案例中监听该事件的指令数量。

http://plnkr.co/edit/wBmX2TvC3yMXwItfxkgl

brodcast:

$scope.ClickMe = function() {
                  alert('child clicked');
                  $rootScope.$broadcast('child-click');;
                };

听:

$scope.$on('child-click', function (event, args) {
                    alert('Parent clicked');
                });