AngularJS - Watch for changes in a service.
I tend to break my applications up into 3 main groups:
- App Module (primary app controllers)
- App Directives
- App Services
I usually put much of my logic into services that can be used within the app controllers and directives, but only recently discovered that $watch
can be used on more than just your app scope!
In a directive I was working on I make a ngResource
request to get a file tree; the logic for this request is inside a service I've named Tree
.
There are actions that should cause the tree to refresh, but since it was in a service I was having trouble getting that to work well.
Enter $watch
I like watch. Watching for changes can make it pretty seamless when you need to fire actions based on those changes without muddying your markup with ng-change
and ng-click
.
So here's a dumbed down version of my application:
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; });
}
};
});
So instead of watching a key on the scope i'm watching a function that returns the service data.
Why is that cool?
Now, from ANYWHERE in my app (say a user controller, that really doesn't even come close to touching the directive) I can toggle Tree.rebuild
and the directive will update.
App.controller('UserCtrl', function($scope, Tree){
if($scope.user.newFile) Tree.rebuild = true;
})
That simple call will now update the directive, and I didn't even have to resort to $rootScope
assignments!