Angularjs:将所需的指令控制器注入控制器而不是链接功能

mak*_*enz 15 angularjs angularjs-directive

角度正常的用例

如果您有父指令和子指令,则在父指令的控制器中创建方法,并在子指令中需要父控制器.Angular会将父控制器传递给子指令链接函数.

我的用例

我有一个用例,其中child指令是另一个指令的父指令.我在指令中间的指令上面有指令.中间指令是底部最后一个指令所必需的.

在一个简单的世界中,我可以为中间指令创建一个链接方法和一个控制器.link方法使用顶层控制器处理所有内容,中间控制器传递给bottom指令.

在我的情况下,中间指令的控制器中的方法必须调用父级中的方法,所以我需要中间控制器中的顶级控制器而不是中间指令的链接功能!

问题

如何将所需的控制器注入控制器而不是链接功能

angular.module('app').directive('top', function () {
    return {
        $scope: true,
        templateUrl: "top.html",
        controller: function() {
            this.topMethod = function() {
                // do something on top
            }
        }
    }
});

angular.module('app').directive('middle', function () {
    return {
        $scope: true,
        templateUrl: "middle.html",
        require: "^top",
        controller: function($scope, $attrs, topController) {
            this.middleMethod = function() {
                // do something in the middle

                // call something in top controller, this is the part that makes everything so complicated
                topController.topMethod();
            }
        }
    }
});

angular.module('app').directive('bottom', function () {
    return {
        $scope: true,
        templateUrl: "bottom.html",
        require: "^middle",
        link: function(scope, element, attrs, middleController) {
            $scope.bottomMethod = function() {
                // do something at the bottom

                // call something in the parent controller
                middleController.middleMethod();
            }
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

mak*_*enz 13

实际上还有另一种不那么冗长的方式,它由角度ngModel本身使用:

var parentForm = $element.inheritedData('$formController') || ....
Run Code Online (Sandbox Code Playgroud)

基本上,它们使用控制器存储在指令dom元素的data属性中的事实.

仍然有点连线,但更简洁,更容易理解.

我没有看到为什么你不能将所需的控制器传递到指令控制器的注入局部的原因.

  • 似乎有更简单的方法来实现这个:var parentForm = $ element.controller('form') (6认同)

mic*_*ael 11

问题在于编写和链接指令的顺序.假设我们有一个像这样的html结构:

<div top>
   <div middle>
      <div bottom></div>
   </div>
</div>
Run Code Online (Sandbox Code Playgroud)

以及具有大量调试输出的相应(简单)指令:

.directive('top', function() {
    return {
        controller : function($scope, $element, $attrs) {
            this.topMethod = function() {
                console.log('top method');
            }
        },
        compile : function($element, $attrs) {
            console.log('top compile');
            return {
                pre : function($scope, $element, $attrs) {
                    console.log('top pre');
                },
                post : function($scope, $element, $attrs) {
                    console.log('top post');
                }
            };
        }
    }
})

.directive('middle', function() {
    return {
        require : "^top",
        controller : function($scope, $element, $attrs) {
            this.middleMethod = function() {
                console.log('middle method');
                $scope.topController.topMethod();
            }
        },
        compile : function($element, $attrs) {
            console.log('middle compile');
            return {
                pre : function($scope, $element, $attrs, topController) {
                    console.log('middle pre');
                    $scope.topController = topController;
                },
                post : function($scope, $element, $attrs, topController) {
                    console.log('middle post');
                }
            };
        },
    }
})

.directive( 'bottom', function() {
    return {
        require : "^middle",
        compile : function($element, $attrs) {
            console.log('bottom compile');
            return {
                pre : function($scope, $element, $attrs, middleController) {
                    console.log('bottom pre');
                    middleController.middleMethod();
                },
                post : function($scope, $element, $attrs, middleController) {
                    console.log('bottom post');
                }
            };
        }
    }
})
Run Code Online (Sandbox Code Playgroud)

我们得到以下输出:

top compile
middle compile
bottom compile

top pre
middle pre
bottom pre

middle method
top method

bottom post
middle post
top post
Run Code Online (Sandbox Code Playgroud)

我们可以先看到编译函数被调用.然后调用预链接函数,之后调用后连接函数.编译和预先从上到下,帖子从下到上.所以我们必须在预连接功能中设置控制器.


fel*_*ker 7

取自romario333的评论:最干净的解决方案是简单地使用

var topController = $element.controller('top') // pass directive name or controller name
Run Code Online (Sandbox Code Playgroud)

来自文档:

controller(name) - 检索当前元素或其父元素的控制器.默认情况下,检索与ngController指令关联的控制器.如果name作为camelCase指令名提供,则将检索该指令的控制器(例如'ngModel').

$ element可以注入到指令控制器中.