AngularJS指令控制器需要父指令控制器?

nic*_*las 30 angularjs angularjs-directive angularjs-scope

我可能会完全倒退,但我正在尝试制作三个嵌套指令,让我们调用它们:屏幕,组件和小部件.我希望widget能够触发组件中的某些行为,从而触发屏幕中的某些行为.所以:

.directive('screen', function() {
    return {
        scope: true,
        controller: function() {
            this.doSomethingScreeny = function() {
                alert("screeny!");
            }
        }
    }
})

.directive('component', function() {
    return {
        scope: true,
        controller: function() {
            this.componentFunction = function() {
                WHAT.doSomethingScreeny();
            }
        }
    }
})

.directive('widget', function() {
    return {
        scope: true,
        require: "^component",
        link: function(scope, element, attrs, componentCtrl) {
            scope.widgetIt = function() {
                componentCtrl.componentFunction();
            };
        }
    }
})

<div screen>
    <div component>
        <div widget>
            <button ng-click="widgetIt()">Woo Hoo</button>
        </div>
    </div>
</div>
Run Code Online (Sandbox Code Playgroud)

我可以在小部件的链接fn中使用父组件require: "^component",但是如何进一步让组件控制器访问其包含的屏幕?

我需要的是组件中的内容,因此当您单击小部件的按钮时,它会提醒"screeny!".

谢谢.

Mar*_*cok 36

您可以通过以下两种方式解决问题:

  1. 由于您正在使用scope: true,所有范围都是原型继承的.所以,如果你确定你的方法$scope,而不是对thisscreen控制器,那么两个componentwidget可以访问功能doSomethingScreeny.
    小提琴.
  2. component和上定义链接功能require: '^screen'.在link函数中,将screenCtrl保存到scope属性,然后可以在指令的控制器中访问它(inject $scope).
    小提琴.

  • 控制器允许您的指令进行交互(只需要获取对控制器的引用),并且控制器总是比指令更容易测试,因为它们不需要您在测试时模拟DOM或模板. (2认同)

mal*_*lte 5

当你想在控制器创建时直接从父控制器访问属性或方法时,大多数这些东西都会失败.我通过使用依赖注入和使用$controller服务找到了另一种解决方案.

.directive('screen', function ($controller) {
    return {
       require: '^parent',
       scope: {},
       link: function (scope, element, attr, controller) {
           $controller('MyCtrl', {
                $scope: scope,
                $element: element,
                $attr, attr, 
                controller: controller
           });
       }
    }
})

.controller('MyCtrl, function ($scope, $element, $attr, controller) {});
Run Code Online (Sandbox Code Playgroud)

此方法更易于测试,并且不会使用不需要的控制器污染您的范围.