Abbiamo visto come lo scope isolato di una direttiva ci consenta di mappare le variabili dello scope di un controller sulle variabili di scope della direttiva, rendendo le direttive componenti autonomi e pienamente riutilizzabili.
Le tre modalità di mapping dello scope
Nella mappatura tra le variabili di scope abbiamo visto l'utilizzo dell'operatore uguale(=
) che consente di specificare la corrispondenza tra il nome della variabile di scope della direttiva e il nome dell'attributo. Abbiamo discusso anche di come non specificare il nome dell'attributo e lasciare il solo operatore =
. Tale operatore rappresenta una delle tre possibili modalità di mappatura tra l'interno della direttiva e l'esterno:
Operatore | Simbolo | Descrizione |
---|---|---|
uguale | = | associa le variabili di scope di direttiva a un attributo |
chiocciola | @ | usare le stringhe per indicare la variabile giusta da considerare nel binding |
e-commerciale | & | permette di valutare espressioni ed eseguire funzioni nel contesto dello scope del controller |
Esaminiamole nel dettaglio partendo dall'operatore che conosciamo già.
Operatore 'uguale' (=)
L'operatore =
rappresenta una mappatura che mette in corrispondenza la variabile esterna con la variabile interna tramite un binding bidirezionale. Cioè, l'oggetto rappresentato dalla variabile è condiviso tra la direttiva e il controller (o qualunque altro componente che la ospita). Eventuali modifiche alla variabile effettuate all'interno della direttiva si riflettono anche all'esterno.
Vedremo più avanti come una direttiva può modificare le variabili dello scope.
Operatore 'chiocciola' (@)
L'operatore @
consente di interpretare come stringhe valori provenienti dall'esterno. Per comprendere meglio l'uso di questo operatore, riprendiamo la nostra direttiva d'esempio e notiamo come abbiamo passato il nome della proprietà da utilizzare per il binding delle option
della select
:
<my-select-city
city-list="elencoCitta"
city-display-property="'nome'">
</my-select-city>
All'attributo city-display-property
abbiamo assegnato un valore che rappresenta una stringa ('nome'
). Se avessimo indicato semplicemente nome
, questa sarebbe estata interpretata come una variabile di scope
che ha naturalmente valore undefined
(o nel peggiore dei casi poteva coincidere con una variabile esistente nello scope
del controller
ma con un valore diverso da quello che ci aspettiamo).
Per gestire al meglio situazioni di questo tipo possiamo definire la mappatura delle variabili sfruttando l'operatore @, come mostrato di seguito:
angular.module("myApp", [])
.directive("mySelectCity", function() {
return {
restrict: "E",
templateUrl: "/mySelectCityTemplate.html",
scope: {
cityList: "=",
cityDisplayProperty: "@"
}
};
});
Con questo accorgimento potremo indicare la proprietà da utilizzare nel binding semplicemente come city-display-property = "name"
.
Operatore 'e-commerciale' (&)
L'operatore &
consente di valutare espressioni ed eseguire funzioni nel contesto dello scope del controller che usa la direttiva. Per comprendere il suo funzionamento, supponiamo di voler estendere la nostra direttiva in modo tale da consentire lo svuotamento dell'elenco delle città aggiungendo un pulsante apposito:
Dal momento però che l'elenco delle città proviene dall'esterno della direttiva, vorremmo che anche le modalità di svuotamento venissero definite all'esterno, almeno per una questione di coerenza della gestione dei dati. Supponiamo che il nostro controller abbia definito la seguente funzione svuotaCitta()
sullo scope:
$scope.svuotaCitta = function() {
$scope.elencoCitta = [];
};
Per consentire alla direttiva di accedere ed eseguire questa funzione prendendo come contesto di riferimento lo scope del controller, definiremo la proprietà emptyAction
nello scope della direttiva sfruttando l'operatore &
:
angular.module("myApp", [])
.directive("mySelectCity", function() {
return {
restrict: "E",
templateUrl: "/mySelectCityTemplate.html",
scope: {
cityList: "=",
cityDisplayProperty: "@",
emptyAction: "&"
}
};
});
Questa proprietà sarà mappata all'attributo empty-action
della direttiva a cui verrà assegnata la chiamata della funzione svuotaCitta
:
<my-select-city
city-list="elencoCitta"
city-display-property="nome"
empty-action="svuotaCitta()">
</my-select-city>
Infine, nel template della direttiva assegnamo l'esecuzione effettiva dell'azione:
<script type="text/ng-template" id="/mySelectCityTemplate.html">
<select ng-model="selectedItem"
ng-options="city[cityDisplayProperty] for city in cityList">
</select>
<button ng-click="emptyAction()">Svuota</button>
</script>
Con questa configurazione, quando l'utente clicca sul pulsante Svuota
, grazie alla mappatura definita con l'operatore & viene eseguita la funzione svuotaCitta()
definita nello scope
del controller
.