Контроллеры директив AngularJS, требующие родительских директивных контроллеров?
Я мог бы подумать об этом полностью назад, но я пытаюсь сделать три вложенных директивы, позвонил им: экран, компонент и виджет. Я хочу, чтобы виджет мог запускать некоторое поведение в компоненте, что, в свою очередь, вызывает некоторое поведение на экране. Итак:
.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>
Я могу потребовать родительские компоненты в ссылке fn виджета с помощью require: "^component"
, но как я могу предоставить контроллеру компонентов доступ к его экрану?
Что мне нужно - это WHAT в компоненте, поэтому, когда вы нажимаете кнопку виджета, он предупреждает "скрипучий!".
Спасибо.
Ответы
Ответ 1
Вот два способа решения вашей проблемы:
- Поскольку вы используете
scope: true
, все области, на которые наследуется прототип. Поэтому, если вы определяете свои методы на $scope
вместо this
в контроллере screen
, то оба component
и widget
будут иметь доступ к функции doSomethingScreeny
.
Fiddle.
- Определите функцию связи на
component
и require: '^screen'
. В функции связи сохраните свойство screenCtrl в свойстве scope, затем вы можете получить доступ к нему в контроллере директивы (введите $scope
).
Fiddle.
Ответ 2
Большая часть этих материалов выходит из строя, когда вы хотите напрямую обращаться к свойствам или методам из родительского контроллера при создании контроллера. Я нашел другое решение, используя инъекцию зависимостей и используя службу $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) {});
Этот метод лучше тестируется и не загрязняет вашу область с помощью нежелательных контроллеров.
Ответ 3
return {scope: true} или return {scope: false} не влияет на переменную $scope в контроллере: function ($ scope) {} в каждой директиве, но тег директивы должен быть помещен в ng-контроллер или ng -app.
JSFiddle
JSFiddle
Ответ 4
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>