Eu tendo a dividir meus aplicativos em 3 grupos principais:
- Módulo de aplicativo (controladores de aplicativo primários)
- Diretivas de aplicativos
- Serviços de aplicativos
Normalmente coloco muito da minha lógica em serviços que podem ser usados dentro dos controladores e diretivas do aplicativo, mas só recentemente descobri que $watch
podem ser usados em mais do que apenas o escopo do seu aplicativo!
Em uma diretiva na qual estava trabalhando, ngResource
solicitei uma árvore de arquivos; a lógica para essa solicitação está dentro de um serviço que nomeei Tree
.
Existem ações que devem fazer com que a árvore seja atualizada, mas como estava em um serviço, não estava conseguindo fazer com que funcionasse bem.
Insira $ watch
Eu gosto de assistir. Observar as alterações pode tornar bastante simples quando você precisa disparar ações com base nessas alterações sem turvar sua marcação com ng-change
e ng-click
.
Então, aqui está uma versão simplificada do meu aplicativo:
var App = app.module('ExampleApp', []);
/**
* Dummy Service
*/
App.service('Tree', function(){
this.rebuild = false;
this.Build = function(cb){
// resource request to get tree hierarcy
cb(response);
};
return this;
});
App.directive('treeView', function(Tree){
return {
restrict: 'A',
link: function(scope, elem, attrs){
scope.data = []; // The directive template will loop this data
// Watch for changes in the service
scope.$watch(function(){
return Tree.rebuild;
}, function(newVal, oldVal){
if(newVal) Tree.Build(function(response){ scope.data = response; Tree.rebuild = false; });
}
};
});
Portanto, em vez de observar uma chave no escopo, estou observando uma função que retorna os dados do serviço.
Por que isso é legal?
Agora, de QUALQUER LUGAR no meu aplicativo (digamos, um controlador de usuário, que realmente nem chega perto de tocar na diretiva), posso alternar Tree.rebuild
e a diretiva será atualizada.
App.controller('UserCtrl', function($scope, Tree){
if($scope.user.newFile) Tree.rebuild = true;
})
Essa chamada simples agora atualizará a diretiva, e eu nem precisei recorrer a $rootScope
atribuições!