Directiva AngularJS – Escopos

Pretendo falar sobre as Directivas AngularJS e diferentes tipos de escopos que podem ser usados. Existem 3 formas principais de passar o escopo para a diretiva a partir da visão invocadora (HTML):

  • Escopo Padrão
  • Escopo Merecido
  • Escopo Isolado

E o próprio escopo isolado poderia ser:

>

  • Neway
  • Twoway
  • Referência do Método

Escopo Padrão

Neste tipo, o escopo da vista externa apenas flui para a diretriz. Para colocar de outra forma, o escopo é passado como “referência” para a diretriz. Todos os dados do escopo estarão imediatamente disponíveis dentro da diretriz para consumo. Da mesma forma, qualquer alteração feita no escopo dentro da diretiva será refletida na visão invocadora imediatamente.

visão e diretriz vinculada ao escopo

Isso é conseguido especificando o escopo como

scope: false // false is the default value

na definição da diretriz.

No exemplo abaixo, ‘nome’ é enviado para a diretriz e qualquer alteração feita é refletida para fora imediatamente. Como o escopo é definido como verdadeiro, a diretiva recebe o escopo como seu chamador. Agora qualquer alteração feita no nome na diretiva será refletida imediatamente no 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>'
}
});

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

Inherited Scope

Neste tipo um novo escopo é herdado do view scope. Em Javascript, os objetos são herdados usando herança prototípica. Estes cenários são descritos no diagrama abaixo:

Isto é conseguido especificando o escopo como

scope: true

na definição da diretiva.

No exemplo abaixo, você pode tentar mudar o nome na diretiva. Esta alteração não será refletida fora devido ao escopo ‘herdado’. O valor só flui dentro mas qualquer alteração resultará em uma cópia para a diretiva e não será refletida fora.

No exemplo abaixo, você pode ver que o ‘nome’ é enviado para a diretiva; mas a alteração feita na diretiva não será refletida fora.

No exemplo abaixo, o escopo da diretiva é dado um valor verdadeiro. Isto significa que um escopo é criado para a diretiva que “herda” a partir do escopo do controlador. Conforme as regras de herança prototípica do javascript, o objeto derivado (escopo da diretiva) se refere às mesmas propriedades do objeto pai (escopo do controlador). Qualquer alteração feita no controlador será refletida na diretiva, até que uma alteração seja feita na propriedade “name” da diretiva. Naquele momento um novo objeto é criado para diretriz e as alterações são opacas entre si.

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

Live fiddle é @ https://jsfiddle.net/madhanganesh/57sb6yg8/

Isolated Scope

Neste tipo de definição de escopo a diretriz recebe um escopo independente que não recebe ou envia de volta nenhum dado para conter a visualização.

>

Isso é conseguido especificando o escopo como

scope: {}

na definição da diretriz.

No exemplo abaixo o escopo isolado é alcançado passando um objeto vazio {} para a diretiva.

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

O violino vivo é @ https://jsfiddle.net/madhanganesh/7d37w08e/

O escopo isolado é realmente mais do que restringir completamente qualquer dado a ser passado dentro (e fora) da diretiva. Em um extremo do espectro você pode restringir completamente os dados como mostrado no exemplo acima. Mas é possível passar um ou mais atributos para a diretiva e capturá-los como um escopo para a diretiva. A flexibilidade vem na forma como o atributo passado é interpretado dentro da diretriz. O atributo passado à diretiva pode ser interpretado de uma das 3 maneiras:

  • como um oneway que é avaliado antes de passar à diretiva
  • como um twoway uma referência à propriedade no escopo da chamada
  • como uma referência ao método no escopo da chamada

Expressão

O chamador da diretiva pode passar explicitamente um valor como mostrado abaixo:

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

A forma como é capturado dentro da diretiva é:

scope: {
name: '@name'
}

@ símbolo diz angular para considerar o atributo nome como uma expressão e avaliá-lo antes de atribuir o valor à propriedade texto. Como a expressão é avaliada, ela é um binding unidirecional e qualquer atualização feita no valor dentro da diretiva não será refletida fora.

No exemplo abaixo, veja que a propriedade nome é passada para a diretiva. Esta é uma expressão que é avaliada e atribuída ao escopo isolado da diretriz. Isto significa que o valor “Jack” é avaliado e atribuído como texto dentro da diretiva.

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

Fiddle live é @ https://jsfiddle.net/madhanganesh/ybzcryt0/4/

Porque o nome é um texto na diretiva as mudanças são locais para a diretiva e nada é compartilhado com o controlador pai.

Dois sentidos (referência à propriedade)

O chamador da diretiva pode passar uma referência a uma propriedade para a diretiva, como em:

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

A forma como ela é capturada dentro da diretiva é:

scope: {
name: '=name'
}

= símbolo diz angular para considerar o atributo nome como uma referência a uma propriedade específica do escopo da chamada. Então o valor é passado para dentro da diretiva e qualquer alteração feita no atributo é refletida fora imediatamente.

>No exemplo abaixo, veja que a propriedade name é passada para a diretiva. Esta é uma referência à propriedade name no escopo 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>'
}
});

Fiddle live é @ https://jsfiddle.net/madhanganesh/o74nvcj3/1/

Porque name é uma referência à propriedade no controller quaisquer alterações em ambos os lados serão refletidas para ambos.

Referência ao método

A forma como é passada da vista de chamada é:

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

A forma como é capturada dentro da diretiva é:

scope: {
nameFn: '& nameFn'
}

& Símbolo diz angular para considerar o atributo nameFn como uma referência a um método específico de escopo de chamada. Este método pode então ser executado de dentro da diretiva quando requerido.

No exemplo abaixo, você pode ver que a propriedade nameFn é um método cuja referência é passada dentro da diretiva. Esta função é executada a partir da diretiva mas avaliada no contexto da chamada de escopo.

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 é @ https://jsfiddle.net/madhanganesh/6w4msr5k/1/

Sumário

Como você pode ver o escopo da diretiva é bastante exaustivo, abaixo do sumário captura as possibilidades e seu significado.

  • Default : A diretiva obtém o mesmo escopo que a vista que a contém
  • Herdada: Diretriz obtém um escopo que é herdado do escopo de conter a view
  • Isolado: Diretriz obtém um escopo que independe de conter view

E dentro do escopo Isolado há 3 possibilidades:

Auto : O atributo diretriz é considerado como uma expressão e avaliado antes de atribuir a propriedade específica do escopo isolado da diretriz