Lorsque vous créez une directive, vous pouvez insérer du code dans le compilateur, la fonction de liaison ou le contrôleur.
Dans la documentation, ils expliquent que:
Cependant, pour moi, il est difficile de savoir quel type de code devrait aller où.
Exemple: puis-je créer des fonctions en compilation et les avoir attachées à la portée en lien ou seulement attacher des fonctions à la portée dans le contrôleur?
Comment les contrôleurs sont-ils partagés entre les directives, si chaque directive peut avoir son propre contrôleur? Les contrôleurs sont-ils vraiment partagés ou s'agit-il uniquement des propriétés de la portée?
Compiler:
C'est la phase où Angular compile réellement votre directive. Cette fonction de compilation est appelée une seule fois pour chaque référence à la directive donnée. Par exemple, supposons que vous utilisiez la directive ng-repeat. ng-repeat devra rechercher l'élément auquel il est attaché, extraire le fragment html auquel il est attaché et créer une fonction de modèle.
Si vous avez utilisé des HandleBars, des modèles de soulignement ou un équivalent, cela revient à compiler leurs modèles pour extraire une fonction de modèle. Pour cette fonction de modèle, vous transmettez des données et la valeur de retour de cette fonction est le code HTML avec les données aux bons endroits.
La phase de compilation est cette étape dans Angular qui renvoie la fonction template. Cette fonction modèle dans angular s'appelle la fonction de liaison.
Phase de liaison:
La phase de liaison est l'endroit où vous attachez les données ($ scope) à la fonction de liaison et devrait vous renvoyer le code HTML lié. Comme la directive spécifie également où ce code HTML va ou ce qu'il change, il est déjà bon de partir. C’est la fonction dans laquelle vous souhaitez modifier le code HTML lié, c’est-à-dire le code HTML auquel les données sont déjà associées. Dans angular si vous écrivez du code dans la fonction de liaison, c'est généralement la fonction post-link (par défaut). C'est en quelque sorte un rappel qui est appelé une fois que la fonction de liaison a lié les données au modèle.
Contrôleur:
Le contrôleur est un endroit où vous insérez une logique spécifique à une directive. Cette logique peut également entrer dans la fonction de liaison, mais vous devrez alors mettre cette logique sur la portée pour la rendre "partageable". Le problème avec cela est que vous corrompriez alors la portée avec vos directives, ce qui n’est pas vraiment quelque chose d’espéré. Alors, quelle est l'alternative si deux directives veulent se parler/coopérer l'une avec l'autre? Bien sûr, vous pouvez mettre toute cette logique dans un service et ensuite faire en sorte que ces deux directives dépendent de ce service, mais cela ne crée qu'une dépendance supplémentaire. L'alternative consiste à fournir un contrôleur pour cette portée (généralement une portée isolée?), Puis ce contrôleur est injecté dans une autre directive lorsque cette directive "requiert" l'autre. Voir les onglets et les panneaux sur la première page de angularjs.org pour un exemple.
Je voulais également ajouter ce que dit le livre O'Reily AngularJS de l'équipe Google:
Contrôleur - Créez un contrôleur qui publie une API pour la communication entre les directives. Un bon exemple est directive à directive
Lien - Modifiez par programme les instances d'élément DOM résultantes, ajoutez des écouteurs d'événement et configurez la liaison de données.
Compiler - Modifiez par programme le modèle DOM pour les fonctionnalités sur les copies d'une directive, comme dans ng-repeat. Votre fonction de compilation peut également renvoyer des fonctions de lien pour modifier les instances d'élément résultantes.
Un directive
vous permet d'étendre le vocabulaire HTML de manière déclarative pour la construction de composants Web. L'attribut ng-app
est une directive, donc ng-controller
et tous les ng- prefixed attributes
. Les directives peuvent être attributes
, tags
ou même class
names
, comments
.
Comment les directives sont nées (compilation
et instantiation
)
Compile: Nous allons utiliser la fonction compile
à la fois manipulate
le DOM avant son rendu et renvoyer une fonction link
(qui gérera la liaison pour nous) . C’est aussi l’endroit idéal pour mettre toutes les méthodes devant être partagées avec tous les instances
de cette directive.
link: Nous allons utiliser la fonction link
pour enregistrer tous les écouteurs sur un élément DOM spécifique (cloné à partir du modèle) et configurer nos liaisons à la page.
Si elles sont définies dans la fonction compile()
, elles n’auraient été configurées qu’une fois (ce que vous voulez souvent). Si elles sont définies dans la fonction link()
, elles le seraient chaque fois que l'élément HTML est lié aux données de l'objet.
<div ng-repeat="i in [0,1,2]">
<simple>
<div>Inner content</div>
</simple>
</div>
app.directive("simple", function(){
return {
restrict: "EA",
transclude:true,
template:"<div>{{label}}<div ng-transclude></div></div>",
compile: function(element, attributes){
return {
pre: function(scope, element, attributes, controller, transcludeFn){
},
post: function(scope, element, attributes, controller, transcludeFn){
}
}
},
controller: function($scope){
}
};
});
La fonction Compile
renvoie les fonctions lien pre
et post
. Dans la fonction de pré-lien, nous avons le modèle d'instance et la portée de la variable controller
, mais le modèle n'est pas lié à la portée et n'a toujours pas de contenu inclus.
Post
La fonction link est où post link est la dernière fonction à exécuter. Maintenant, la transclusion
est terminée, the template is linked to a scope
et le view will update with data bound values after the next digest cycle
. L'option link
n'est qu'un raccourci pour configurer une fonction post-link
.
controller: Le contrôleur de directive peut être passé à une autre phase de liaison/compilation de directive. Il peut être injecté dans d'autres directeurs en tant que moyen à utiliser dans la communication inter-directive.
Vous devez spécifier le nom de la directive requise - Elle doit être liée au même élément ou à son parent. Le nom peut être préfixé par:
? – Will not raise any error if a mentioned directive does not exist.
^ – Will look for the directive on parent elements, if not available on the same element.
Utilisez le crochet [‘directive1′, ‘directive2′, ‘directive3′]
pour imposer plusieurs directives au contrôleur.
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope, $element) {
});
app.directive('parentDirective', function() {
return {
restrict: 'E',
template: '<child-directive></child-directive>',
controller: function($scope, $element){
this.variable = "Hi Vinothbabu"
}
}
});
app.directive('childDirective', function() {
return {
restrict: 'E',
template: '<h1>I am child</h1>',
replace: true,
require: '^parentDirective',
link: function($scope, $element, attr, parentDirectCtrl){
//you now have access to parentDirectCtrl.variable
}
}
});
De plus, une bonne raison d'utiliser une fonction de contrôleur ou de liaison (car ils ont tous deux accès à la portée, à l'élément et aux attrs) est que vous pouvez transférer n'importe quel service ou dépendance disponible dans un contrôleur (et dans n'importe quel ordre), vous ne pouvez pas faire cela avec la fonction de lien. Notez les différentes signatures:
controller: function($scope, $exceptionHandler, $attr, $element, $parse, $myOtherService, someCrazyDependency) {...
vs.
link: function(scope, element, attrs) {... //no services allowed
c'est un bon exemple pour comprendre les phases de directive http://codepen.io/anon/pen/oXMdBQ?editors=101
var app = angular.module('myapp', [])
app.directive('slngStylePrelink', function() {
return {
scope: {
drctvName: '@'
},
controller: function($scope) {
console.log('controller for ', $scope.drctvName);
},
compile: function(element, attr) {
console.log("compile for ", attr.name)
return {
post: function($scope, element, attr) {
console.log('post link for ', attr.name)
},
pre: function($scope, element, attr) {
$scope.element = element;
console.log('pre link for ', attr.name)
// from angular.js 1.4.1
function ngStyleWatchAction(newStyles, oldStyles) {
if (oldStyles && (newStyles !== oldStyles)) {
forEach(oldStyles, function(val, style) {
element.css(style, '');
});
}
if (newStyles) element.css(newStyles);
}
$scope.$watch(attr.slngStylePrelink, ngStyleWatchAction, true);
// Run immediately, because the watcher's first run is async
ngStyleWatchAction($scope.$eval(attr.slngStylePrelink));
}
};
}
};
});
html
<body ng-app="myapp">
<div slng-style-prelink="{height:'500px'}" drctv-name='parent' style="border:1px solid" name="parent">
<div slng-style-prelink="{height:'50%'}" drctv-name='child' style="border:1px solid red" name='child'>
</div>
</div>
</body>