I need to communicate state which several services need and originates in data bound to the scope of a controller. What would a good and \'Angular zen\' way to
Very interesting question.
We've been using angular for a few months now and are currently considering how this can be done better. We're still trying to figure out what can be an optimal solution, maybe this will help in getting there.
I think the original solution you've provided is pretty similar, but there are a few considerations which should be taken:
I also believe using a shared service which is injected when needed is the way to go.
I've modified Ilan Frumer's cool plunker example: http://plnkr.co/edit/YffbhCMJbTPdcjZDl0UF?p=preview
Breaking down the problem into two can help in thinking of what can be a solution.
Updating the config service with changes done in the settings page
For this, using a $watch looks like the optimal solution, you wait for the specific config to be changes and as a response let the config service know what have been changed. I prefer of doing it explicitly, to keep the flow of the change clear and consistent.
This can be done by making a local copy of the Configuration data and watching for changes.
app.factory('Configuration', function($rootScope){
return {
var config = {
user: "xxxx"
}
return {
config: config,
set: function(item, value) {
config[item] = value;
$rootScope.$emit("configChanged." + item);
},
changed: function(item, callback, scope) {
var deregister = $rootScope.$on("configChanged." + item, function() {
callback(config[item], config)
});
callback(config[item], config);
if (scope) {
scope.$on("$destroy", deregister);
}
}
}
}
});
app.controller('SettingsCtrl', function($scope, $timeout, Configuration){
// Get a local copy - configuration shouldn't change until change
// is completed
$scope.data = angular.copy(Configuration.config);
// Keep UI interactions in the controller
// If more complex UI is required another way could even use a
// directive for this
$scope.$watch("data.user", function(user) {
Configuration.set('user', $scope.data.user);
});
});
app.factory('DetailsService', function(Configuration, $http){
var details = {
data : null,
};
Configuration.changed("user", function(user) {
// Handle user change ...
});
});
How services / controllers observe changes
This also has two options.
In case there are multiple states services, another optimization can be to extract the "set", "changed" functions to a generic implementation.
Hope it helps.