Direttiva AngularJS – Scopi

Intendo parlare delle direttive AngularJS e dei diversi tipi di scope che possono essere usati. Ci sono 3 modi principali in cui lo scope può essere passato alla direttiva dalla vista invocante (HTML):

  • Default Scope
  • Inherited Scope
  • Isolated Scope

E lo scope isolato potrebbe essere:

  • Oneway
  • Twoway
  • Method Reference

Default Scope

In questo tipo, lo scope dalla vista esterna fluisce semplicemente nella direttiva. Per dirla in un altro modo, l’ambito viene passato come “riferimento” alla direttiva. Tutti i dati dell’ambito saranno immediatamente disponibili all’interno della direttiva per essere consumati. Allo stesso modo, qualsiasi modifica apportata allo scope all’interno della direttiva si rifletterà immediatamente nella vista invocante.

view e direttiva bound vis scope

Questo si ottiene specificando lo scope come

scope: false // false is the default value

nella definizione della direttiva.

Nell’esempio qui sotto, ‘nome’ è volato nella direttiva e qualsiasi cambiamento fatto si riflette immediatamente all’esterno. Poiché l’ambito è impostato true, la direttiva ottiene l’ambito come suo chiamante. Ora qualsiasi cambiamento fatto al nome nella direttiva si rifletterà immediatamente nel controller ‘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>'
}
});

Il fiddle vivente è @ https://jsfiddle.net/madhanganesh/830rn1fm/

Inherherited Scope

In questo tipo un nuovo ambito viene ereditato dall’ambito della vista. In Javascript, gli oggetti sono ereditati usando l’ereditarietà prototipica. Questo scenario è rappresentato nel diagramma qui sotto:

Questo si ottiene specificando lo scope come

scope: true

nella definizione della direttiva.

Nell’esempio qui sotto potete provare a cambiare il nome nella direttiva. Questo cambiamento non si rifletterà all’esterno a causa dell’ambito “ereditato”. Il valore scorre solo all’interno, ma qualsiasi cambiamento risulterà in una copia per la direttiva e non sarà riflesso all’esterno.

Nell’esempio live qui sotto, potete vedere che il ‘nome’ è volato nella direttiva; ma il cambiamento fatto nella direttiva non sarà riflesso all’esterno.

Nell’esempio qui sotto, all’ambito della direttiva è dato un valore di true. Questo significa che viene creato uno scope per la direttiva che “eredita” dallo scope del controller. Come per le regole di ereditarietà prototipiche di javascript, l’oggetto derivato (scope della direttiva) fa riferimento alle stesse proprietà dell’oggetto padre (scope del controller). Qualsiasi modifica apportata al controller si rifletterà nella direttiva, fino a quando non viene apportata una modifica alla proprietà “name” nella direttiva. In quel momento viene creato un nuovo oggetto per la direttiva e le modifiche sono opache l’una dall’altra.

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>'
}
});

Il fiddle live è @ https://jsfiddle.net/madhanganesh/57sb6yg8/

Isolated Scope

In questo tipo di definizione dello scope la direttiva ottiene uno scope indipendente che non riceve o rimanda alcun dato alla vista contenente.

Questo si ottiene specificando lo scope come

scope: {}

nella definizione della direttiva.

Nell’esempio qui sotto lo scope isolato si ottiene passando un oggetto vuoto {} alla direttiva.

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>'
}
});

Il live fiddle è @ https://jsfiddle.net/madhanganesh/7d37w08e/

Lo scope isolato è davvero più che limitare completamente qualsiasi dato da passare dentro (e fuori) dalla direttiva. Ad un’estremità dello spettro è possibile limitare completamente i dati come mostrato nell’esempio precedente. Ma è possibile passare uno o più attributi alla direttiva e catturarli come scope per la direttiva. La flessibilità sta nel modo in cui l’attributo passato viene interpretato all’interno della direttiva. L’attributo passato alla direttiva potrebbe essere interpretato in uno dei 3 modi seguenti:

  • come una via unica che viene valutata prima di passare alla direttiva
  • come una via doppia un riferimento alla proprietà nello scope chiamante
  • come un riferimento al metodo nello scope chiamante

Espressione

Il chiamante della direttiva può passare esplicitamente un valore come mostrato sotto:

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

Il modo in cui viene catturato all’interno della direttiva è:

scope: {
name: '@name'
}

@ simbolo dice ad angular di considerare l’attributo name come un’espressione e valutarla prima di assegnare il valore alla proprietà text. Poiché l’espressione viene valutata, è un binding a senso unico e qualsiasi aggiornamento fatto sul valore all’interno della direttiva non si rifletterà all’esterno.

Nell’esempio qui sotto, vedete che la proprietà name viene passata alla direttiva. Questa è un’espressione che viene valutata e assegnata allo scope isolato della direttiva. Questo significa che il valore “Jack” viene valutato e assegnato come testo all’interno della direttiva.

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>'
}
});

Il fiddle vivente è @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/

Perché name è un testo nella direttiva le modifiche sono locali alla direttiva e nulla viene condiviso con il controllore padre.

Two-way (reference to property)

Il chiamante della direttiva può passare un riferimento a una proprietà alla direttiva, come in:

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

Il modo in cui viene catturato all’interno della direttiva è:

scope: {
name: '=name'
}

= simbolo dice ad angular di considerare l’attributo name come un riferimento a una proprietà specifica dello scope chiamante. Quindi il valore viene passato alla direttiva e qualsiasi cambiamento fatto sull’attributo si riflette immediatamente all’esterno.

Nell’esempio qui sotto, vedete che la proprietà name viene passata alla direttiva. Questo è un riferimento alla proprietà name nell’ambito genitore.

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>'
}
});

Il fiddle live è @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/

Perché name è un riferimento alla proprietà nel controller qualsiasi cambiamento su entrambi i lati si rifletterà su entrambi.

Riferimento al metodo

Il modo in cui viene passato dalla vista chiamante è:

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

Il modo in cui viene catturato all’interno della direttiva è:

scope: {
nameFn: '& nameFn'
}

& il simbolo dice ad angular di considerare l’attributo nameFn come un riferimento al metodo specifico dello scope chiamante. Questo metodo può quindi essere eseguito dall’interno della direttiva quando richiesto.

Nell’esempio qui sotto, potete vedere che la proprietà nameFn è un metodo il cui riferimento viene passato all’interno della direttiva. Questa funzione viene eseguita dalla direttiva ma valutata nel contesto dell’ambito chiamante.

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()}}'
}
});

Il violino vivo è @ https://jsfiddle.net/madhanganesh/6w4msr5k/1/

Sommario

Come potete vedere l’ambito della direttiva è abbastanza esaustivo, sotto il sommario cattura le possibilità e il loro significato.

  • Default : la direttiva ottiene lo stesso ambito della sua vista contenente
  • Ereditata: La direttiva ottiene un ambito che è ereditato dall’ambito della vista contenente
  • Isolato: La direttiva ottiene un ambito che è indipendente dalla vista contenente

E all’interno dell’ambito isolato ci sono 3 possibilità:

Oneway : L’attributo della direttiva è considerato come un’espressione e valutato prima di assegnare alla proprietà specifica dell’ambito isolato della direttiva