I have an AngularJs app with a master details that I have changed to use ui-router.
Previously, I had a SelectionService
with a plain JavaScript observer that was
used by the master to notify selection and by the details to update himself. The
selection was just a technical identifier, so that the DetailsController
has
to get the item from my BackendService
which is basically a local cache.
Now with ui-router when an item is selected into the master, I go the details state and the same flow remains (use the technical id to get details from backend).
My problem is that into the previous version all updates made on the details
where automagically updated on the master. But that is broken with the ui-router
version, probably because the MasterController
and DetailsController
don't
share the same scope.
So, my question is : How do you ensure that a list of items is updated when one
item is changed. Do you rely on some AngularJs functionalities (then how) or do
you use a classic events mechanism with $scope.$broadcast
and $scope.$on
?
Edit, after more investigations
I have read some articles that are clearly against the usage of AngularJs events ($scope.$broadcast
, $scope.$emit
and $scope.$on
) and recommand a custom event bus/aggregator.
But I would like to avoid that and thus rely on the AngularJs digest lifecycle. However what is suggest by @Kashif ali below is what I have but my master is not updated when the details changes.
angular
.module('masterDetails')
.service('BackendService', function($q){
var cache = undefined;
var Service = {}
Service.GetImages = function() {
var deferred = $q.defer();
var promise = deferred.promise;
if ( !cache ) {
// HTTP GET from server .then(function(response){
cache = JSON.parse(response.data);
deferred.resolve(cache);
});
} else {
deferred.resolve(cache);
}
return promise;
}
Service.GetImage = function(key) {
return GetImages().then(function(images){
return images[key];
});
}
Service.SetImage = function(key, updated) {
GetImages().then(function(images){
images[key] = updated;
// TODO; HTTP PUT to server
});
}
})
.controller('MasterController', function(BackendService){
var vm = this;
vm.items = [];
vm.onSelect = onSelect;
init();
function init() {
BackendService.GetImages().then(function(images){
// images is a map of { key:String -> Image:Object }
vm.items = Object.keys(images).map(function(key){
return images[key];
});
});
}
function onSelect(image) {
$state.go('state.to.details', {key: image.key});
}
})
.controller('DetailsController', function(BackendService, $stateParams){
var vm = this;
vm.image = undefined;
init();
function init() {
BackendService.GetImage($stateParams.key).then(function(image){
vm.image = image;
}).then(function(){
// required to trigger update on the BackendService
$scope.$watch('[vm.image.title, vm.image.tags]', function(newVal, oldVal){
BackendService.SetImage(vm.image.key, vm.image);
}, true);
});
}
});
Edit, this is due to the states
So, when I open the app on #/images the images
state start. Then I select one image to go to the images.edit
state and everything works well, the master is updated when details changes.
However if I start on #/images/:key which is the images.edit
state, then the master ignore all changes mades on the master.