Directive AngularJS – Scopes

J’ai l’intention de parler des directives AngularJS et des différents types de scopes qui peuvent être utilisés. Il y a 3 façons principales par lesquelles le scope peut être passé à la directive à partir de la vue invoquante (HTML):

  • Default Scope
  • Inherited Scope
  • Isolated Scope

Et le scope isolé pourrait lui-même être :

  • Oneway
  • Twoway
  • Method Reference

Default Scope

Dans ce type, le scope de la vue extérieure se déverse simplement dans la directive. Pour le dire autrement, le scope est passé comme « référence » à la directive. Toutes les données de la portée seront immédiatement disponibles dans la directive pour être consommées. De même, toute modification apportée au scope dans la directive sera immédiatement répercutée dans la vue qui l’invoque.

Vue et directive liées vis scope

Ceci est réalisé en spécifiant le scope as

scope: false // false is the default value

dans la définition de la directive.

Dans l’exemple ci-dessous, ‘nom’ est survolé dans la directive et tout changement effectué est reflété à l’extérieur immédiatement. Parce que la portée est définie à true, directive obtient la portée comme son appelant. Maintenant, tout changement apporté au nom dans la directive sera immédiatement reflété dans le contrôleur ‘MyController’.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: false,
template: 'Name: <input ng-model="name"></input>'
}
});

Live fiddle is @ https://jsfiddle.net/madhanganesh/830rn1fm/

Inherited Scope

Dans ce type, un nouveau scope est hérité du view scope. En Javascript, les objets sont hérités en utilisant l’héritage prototypique. Ce scénario est représenté dans le diagramme ci-dessous :

Ceci est réalisé en spécifiant le scope comme

scope: true

dans la définition de la directive.

Dans l’exemple ci-dessous, vous pouvez essayer de changer le nom dans la directive. Ce changement ne sera pas reflété à l’extérieur en raison de la portée ‘héritée’. La valeur ne circule qu’à l’intérieur mais tout changement entraînera une copie pour la directive et ne sera pas reflété à l’extérieur.

Dans l’exemple en direct ci-dessous, vous pouvez voir que le ‘nom’ est envolé dans la directive ; mais le changement effectué dans la directive ne sera pas reflété à l’extérieur.

Dans l’exemple ci-dessous, la portée de la directive reçoit une valeur de true. Cela signifie qu’une portée est créée pour la directive qui « hérite » de la portée du contrôleur. Selon les règles d’héritage prototypiques de javascript, l’objet dérivé (scope de directive) fait référence aux mêmes propriétés de l’objet parent (scope de controller). Tout changement apporté au contrôleur sera reflété dans la directive, jusqu’à ce qu’un changement soit apporté à la propriété « name » dans la directive. A ce moment-là, un nouvel objet est créé pour la directive et les changements sont opaques les uns des autres.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: true,
template: 'Name: <input ng-model="name"></input>'
}
});

La bidouille vivante est @ https://jsfiddle.net/madhanganesh/57sb6yg8/

Isolated Scope

Dans ce type de définition de scope, la directive obtient un scope indépendant qui ne reçoit ni ne renvoie aucune donnée à la vue contenante.

Ceci est obtenu en spécifiant la portée comme

scope: {}

dans la définition de la directive.

Dans l’exemple ci-dessous, la portée isolée est obtenue en passant un objet vide {} à la directive.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = "Jack";
});// usage: <div upper-case/></div>
myApp.directive('upperCase', function() {
return {
scope: {},
template: 'Name: <input ng-model="name"></input>'
}
});

Live fiddle is @ https://jsfiddle.net/madhanganesh/7d37w08e/

La portée isolée est vraiment plus à cela que de restreindre complètement toute donnée à passer dans (et hors) de la directive. À une extrémité du spectre, vous pouvez complètement restreindre les données comme le montre l’exemple ci-dessus. Mais il est possible de passer un ou plusieurs attributs à la directive et de les capturer en tant que champ d’application de la directive. La flexibilité vient de la façon dont l’attribut passé est interprété dans la directive. L’attribut passé à la directive pourrait être interprété de l’une des 3 manières suivantes :

  • comme un oneway qui est évalué avant de passer à la directive
  • comme un twoway une référence à la propriété dans la portée d’appel
  • comme une référence à la méthode dans la portée d’appel

Expression

L’appelant de la directive peut explicitement passer une valeur comme indiqué ci-dessous :

<div my-directive name='{{name}}' />
// an expression is passed to the directive

La façon dont elle est capturée à l’intérieur de la directive est :

scope: {
name: '@name'
}

@ symbole indique à angular de considérer l’attribut name comme une expression et de l’évaluer avant d’affecter la valeur à la propriété text. Parce que l’expression est évaluée, c’est une liaison à sens unique et toute mise à jour effectuée sur la valeur à l’intérieur de la directive ne sera pas reflétée à l’extérieur.

Dans l’exemple ci-dessous, voyez que la propriété name est passée à la directive. C’est une expression qui est évaluée et assignée à la portée isolée de la directive. Cela signifie que la valeur « Jack » est évaluée et assignée en tant que texte à l’intérieur de la directive.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
});
// usage: <div my-directive name='{{name}}' />
myApp.directive('upperCase', function() {
return {
scope: {
name: '@name'
},
template: 'Name: <input ng-model="name"></input>'
}
});

Le violon vivant est @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/

Parce que name est un texte dans la directive, les changements sont locaux à la directive et rien n’est partagé avec le contrôleur parent.

Double sens (référence à une propriété)

L’appelant de la directive peut passer une référence à une propriété à la directive, comme dans:

<div my-directive name='data.name' />
// a property reference to the directive

La façon dont il est capturé à l’intérieur de la directive est:

scope: {
name: '=name'
}

= symbole indique à angular de considérer l’attribut name comme une référence à une propriété spécifique de la portée appelante. Ainsi, la valeur est passée dans la directive et tout changement effectué sur l’attribut est reflété à l’extérieur immédiatement.

Dans l’exemple ci-dessous, voyez que la propriété name est passée à la directive. C’est une référence à la propriété name dans le scope parent.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
});
myApp.directive('upperCase', function() {
return {
scope: {
name: '=name'
},
template: 'Name: <input ng-model="name"></input>'
}
});

Le fiddle live est @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/

Parce que name est une référence à la propriété dans le contrôleur tout changement de part et d’autre sera reflété aux deux.

Référence à la méthode

La façon dont elle est passée depuis la vue appelante est:

<div my-directive nameFn="getName()" />
// a method reference is passed to the directive

La façon dont elle est capturée à l’intérieur de la directive est:

scope: {
nameFn: '& nameFn'
}

& Le symbole indique à angular de considérer l’attribut nameFn comme une référence à une méthode spécifique de la portée appelante. Cette méthode peut ensuite être exécutée à partir de la directive lorsque cela est nécessaire.

Dans l’exemple ci-dessous, vous pouvez voir que la propriété nameFn est une méthode dont la référence est passée à l’intérieur de la directive. Cette fonction est exécutée à partir de la directive mais évaluée dans le contexte de la portée d’appel.

var myApp = angular.module('myApp', );
myApp.controller('MyController', function($scope) {
$scope.name = 'Jack';
$scope.getName = function() {
return $scope.name;
}
});
myApp.directive('upperCase', function() {
return {
scope: {
nameCb: '&name'
},
//template: 'Name: <input ng-model="nameFn()"></input>'
template: 'Name: {{textCb()}}'
}
});

Live fiddle is @ https://jsfiddle.net/madhanganesh/6w4msr5k/1/

Summary

Comme vous pouvez le voir la portée de la directive est assez exhaustive, le résumé ci-dessous capture les possibilités et leur signification.

  • Default : La directive obtient la même portée que sa vue contenante
  • Inherited : La directive obtient une portée qui est héritée de la portée de la vue contenant
  • Isolé : Directive obtient une portée indépendante de la vue contenante

Et dans la portée isolée, il y a 3 possibilités :

Oneway : L’attribut de la directive est considéré comme une expression et évalué avant d’être assigné à une propriété spécifique de la portée isolée de la directive

.