AngularJS – Die require-Eigenschaft einer Direktive
Dass es Direktiven mit eigenen Controllern gibt, dürfte den meisten AngularJS-Entwicklern bekannt sein. Wem dieses Konzept neu ist, kann hier darüber lesen. Was vielleicht nicht allen vertraut ist, ist der vierte Parameter der link-Funktion einer Direktive. In diesem Artikel werden wir sehen, wie wir auf den Controller einer Direktive zugreifen können. Des weiteren werden wir sehen, wie wir Zugriff auf Controller von anderen Direktiven wie z. B. ng-model bekommen können.
Wie schon angedeutet, können wir mit Hilfe des vierten Parameters der link-Funktion Zugriff auf den Controller der Direktive bekommen. Das ist besonders nützlich, wenn wir mit ControllerAs (wie im oben verlinktem Blogartikel beschrieben), einem isoliertem Scope und bindToController arbeiten. Wenn wir nur Interesse an dem Controller der Direktive haben, geht das ganz einfach:
script.js
angular.module('directiveTest', [])
.directive('meineDirektive', function() {
return {
controller: 'DirCtrl',
controllerAs: 'dirCtrl',
bindToController: true,
scope: {}, // Scope ist isoliert
link: function(scope, element, attrs, ctrl) {
console.log(ctrl.name); // 'MeineDirektive'
}
};
})
.controller('DirCtrl', function() {
this.name = 'MeineDirektive';
});
Ein bisschen komplexer wird es, wenn wir Zugriff auf einen anderen oder auf mehrere Controller brauchen. Dafür nutzen wir die require-Eigenschaft der Direktive.
Beispiel: Zugriff auf einen anderen Controller
Ausschnitt aus index.html
<body ng-app="directiveTest">
<div ng-controller="MainCtrl as mainCtrl">
<input meine-direktive ng-model="mainCtrl.name" />
</div>
<script src="script.js"></script>
</body>
script.js
angular.module('directiveTest', [])
.directive('meineDirektive', function() {
return {
controller: 'DirCtrl',
controllerAs: 'dirCtrl',
bindToController: true,
scope: {}, // Scope ist isoliert
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
// ctrl ist der Controller der ng-model-Direktive
console.log(ctrl.$valid); // true
}
};
})
.controller('DirCtrl', function() {
this.name = 'MeineDirektive';
})
.controller('MainCtrl', function() {
this.name = 'MainCtrl';
});
Hier haben wir als vierten Parameter der Funktion den Controller der ng-model-Direktive statt des Controllers unserer Direktive. Wichtig zu beachten ist, dass require nur mit Controllern von Direktiven funktioniert. Als Wert wird der Name der Direktive erwartet, und als Ergebnis bekommen wir den Controller der Direktive als vierten Parameter der link-Funktion. Wir können aber auch Zugriff auf mehrere Controller gleichzeitig bekommen, indem wir ein Array mit Direktivennamen angeben statt des Namens einer einzelnen Direktive.
Beispiel: Zugriff auf mehrere Controller
Ausschnitt aus index.html
<body ng-app="directiveTest">
<div ng-controller="MainCtrl as mainCtrl">
<input meine-direktive ng-model="mainCtrl.name" />
</div>
<script src="script.js"></script>
</body>
script.js
angular.module('directiveTest', [])
.directive('meineDirektive', function() {
return {
controller: 'DirCtrl',
controllerAs: 'dirCtrl',
bindToController: true,
scope: {}, // Scope ist isoliert
require: ['meineDirektive', 'ngModel'],
link: function(scope, element, attrs, ctrlArray) {
// ctrlArray[0] ist der Controller unserer Direktive
console.log(ctrlArray[0].name); // 'MeineDirektive'
// ctrlArray[1] ist der Controller der ng-model-Direktive
console.log(ctrlArray[1].$valid); // true
}
};
})
.controller('DirCtrl', function() {
this.name = 'MeineDirektive';
})
.controller('MainCtrl', function() {
this.name = 'MainCtrl';
});
Zum Schluss möchte ich noch erwähnen, dass die Namen der Direktive, die wir bei der require-Eigenschaft angeben, auch ein Präfix haben können. Hier noch kurz die verschiedene Präfixe und deren Bedeutung:
- Kein Präfix: Finde den gesuchten Controller auf dem aktuellen Element. Exception wird geworfen, wenn der Controller nicht existiert
- ? : Versuche, den Controller auf dem aktuellen Element zu finden. Wenn dieser nicht existiert, ist der vierte Parameter der Funktion null
- ^ : Finde den gesuchten Controller auf dem aktuellen und auf den übergeordneten Elementen. Exception wird geworfen, wenn der Controller nicht existiert
- ^^ : Finde den gesuchten Controller auf einem übergeordnetem Element. Exception wird geworfen, wenn der Controller nicht existiert
- ?^ : Wie ^ aber mit null statt Exception
- ?^^ : Wie ^^ aber mit null statt Exception