J'y réfléchis peut-être complètement à l'envers, mais j'essaie de créer trois directives imbriquées, appelons-les: écran, composant et widget. Je veux que le widget puisse déclencher un comportement dans le composant, ce qui déclenche un comportement à l'écran. Alors:
.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>
Je peux exiger des composants parents dans le lien fn d'un widget à l'aide de require: "^component"
, mais comment puis-je donner aux composants un accès supplémentaire au contrôleur qui le contient?
Ce dont j'ai besoin, c'est du composant WHAT, donc lorsque vous cliquez sur le bouton du widget, celui-ci alerte "screeny!".
Merci.
Voici deux manières de résoudre votre problème:
scope: true
, toutes les étendues héritent de manière prototypique. Donc, si vous définissez vos méthodes sur $scope
au lieu de this
dans le contrôleur screen
, alors component
et widget
auront accès à la fonction doSomethingScreeny
.component
et require: '^screen'
. Dans la fonction de liaison, enregistrez la propriété screenCtrl dans une propriété de portée, puis accédez-y dans le contrôleur de la directive (inject $scope
) .La plupart de ces commandes échouent lorsque vous souhaitez accéder directement aux propriétés ou aux méthodes à partir du contrôleur parent lors de la création du contrôleur. J'ai trouvé une autre solution en utilisant l'injection de dépendance et le service $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) {});
Cette méthode est mieux testable et ne pollue pas votre portée avec des contrôleurs indésirables.
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>
Si vous souhaitez accéder à une fonction définie dans le contrôleur de directive screen à partir du contrôleur de directive composant (pas une fonction de liaison), vous pouvez utiliser $element.controller('screen').doSomethingScreeny()
(à partir de la directive composant).
Angular documentation :
controller(name)
- récupère le contrôleur de l'élément en cours ou son parent. Récupère par défaut le contrôleur associé au fichier directivengController
. Siname
est fourni comme directive camelCase nom, alors le contrôleur pour cette directive sera récupéré (par exemple .'ngModel'
).