Ich denke vielleicht ganz rückwärts darüber nach, aber ich versuche drei verschachtelte Direktiven zu machen, nennen wir sie: Bildschirm, Komponente und Widget. Ich möchte, dass das Widget in der Lage ist, ein bestimmtes Verhalten in einer Komponente auszulösen, was wiederum ein gewisses Verhalten im Bildschirm auslöst. 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>
Ich kann übergeordnete Komponenten im Link fn eines Widgets mit require: "^component"
verwenden. Wie kann ich Komponentencontroller außerdem Zugriff auf den zugehörigen Bildschirm gewähren?
Was ich brauche, ist das WAS in der Komponente. Wenn Sie auf die Schaltfläche des Widget klicken, wird "screeny!".
Vielen Dank.
Es gibt zwei Möglichkeiten, wie Sie Ihr Problem lösen können:
scope: true
verwenden, erben alle Bereiche prototypisch. Wenn Sie also Ihre Methoden für $scope
statt für this
im Controller screen
definieren, haben sowohl component
als auch widget
Zugriff auf die Funktion doSomethingScreeny
.component
und require: '^screen'
. Speichern Sie in der Link-Funktion die screenCtrl in einer Bereichseigenschaft. Anschließend können Sie im Controller der Direktive darauf zugreifen (inject $scope
) .Die meisten dieser Dinge schlagen fehl, wenn Sie beim Erstellen des Controllers direkt auf die Eigenschaften oder Methoden des übergeordneten Controllers zugreifen möchten. Ich habe eine andere Lösung gefunden, indem ich Abhängigkeitsinjektion und den $controller
-Dienst verwendete.
.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) {});
Diese Methode ist besser prüfbar und belastet Ihren Bereich nicht mit unerwünschten Controllern.
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>
Wenn Sie auf eine in screen - Direktive-Controller definierte Funktion von component - Direktive-Controller (keine Link-Funktion) zugreifen möchten, können Sie $element.controller('screen').doSomethingScreeny()
(von component - Direktive) verwenden.
Winkel Dokumentation :
controller(name)
- ruft den Controller des aktuellen Elements oder .__ ab. sein Elternteil. Ruft standardmäßig den Controller ab, der dem .__ zugeordnet ist.ngController
Direktive. Wennname
als camelCase-Direktive angegeben ist name, dann wird der Controller für diese Direktive abgerufen (z. B. .'ngModel'
).