30

I might be thinking about this completely backwards, but I'm trying to make three nested directives, lets call them: screen, component and widget. I want widget to be able to trigger some behavior in component, which in turn triggers some behavior in screen. So:

.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>

I can require parent components in a widget's link fn using require: "^component", but how do I further give components controller access to its containing screen?

What I need is the WHAT in component so when you click the widget's button it alerts "screeny!".

Thanks.

4

4 回答 4

36

这里有两种方法可以解决您的问题:

  1. 由于您使用的是scope: true,因此所有范围都原型继承。因此,如果您在控制器中定义方法$scope而不是 on ,那么两者和都可以访问 function 。 小提琴thisscreencomponentwidgetdoSomethingScreeny
  2. component在和上定义链接函数require: '^screen'。在链接函数中,将 screenCtrl 保存到范围属性中,然后您可以在指令的控制器中访问它(注入$scope)。
    小提琴
于 2013-03-25T22:00:53.363 回答
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) {});

此方法可更好地测试,并且不会用不需要的控制器污染您的示波器。

于 2015-03-10T15:02:54.583 回答
0

var myApp = angular.module('myApp', [])

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

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

.directive('widget', function() {
  return {
    scope: true,
    controller: function($scope, $element) {
      $scope.widgetFunction = function() {
        $element.controller('component').componentFunction();
      }
    }
  }
})

.controller('MyCtrl', function($scope) {
  $scope.name = 'Superhero';
})
<body ng-app="myApp">

  <div ng-controller="MyCtrl">
    <div screen>
      <div component>
        <div widget>
          <button ng-click="widgetFunction()">Woo Hoo</button>
        </div>
      </div>
    </div>
  </div>

</body>

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

如果要从组件指令控制器(不是链接函数)访问屏幕指令控制器中定义的函数,可以使用(从组件指令)。$element.controller('screen').doSomethingScreeny()

JSFiddle

文件

  • controller(name)- 检索当前元素或其父元素的控制器。默认情况下检索与 ngController指令关联的控制器。如果name作为 camelCase 指令名称提供,则将检索该指令的控制器(例如 'ngModel')。
于 2016-01-28T15:24:49.967 回答
0

return { scope: true } 或 return { scope: false } 不影响控制器中的 $scope 变量:每个指令中的 function($scope) {},但指令标签必须放入 ng-controller 或 ng-app 标签.

JSFiddle

JSFiddle

于 2015-12-02T09:44:38.090 回答