How can I switch out a service on-the-fly and have all components (relying on the service) automatically be bound to the data on the new strategy?
I have a Storage
service and two storage strategies, StorageStrategyA
and StorageStrategyB
. Storage
provides the public interface to controllers and other components to interact with:
angular.module('app').factory('Storage', function ($injector) {
var storage;
var setStrategy = function (name) {
storage = $injector.get(name);
};
setStrategy('StorageStrategyB');
return {
getItems: function () {
return storage.getItems();
}
// [...]
};
});
But when the strategy is changed, the two-way binding breaks and the view doesn't update with items from getItems()
from the new strategy.
I've created a Plunker to illustrate the problem.
Is there a way to combine the strategy pattern with AngularJS and keep the two-way binding?
Please note that in my actual app I cannot just call Storage.getItems()
again after the strategy has been changed, because there are multiple components (views, controllers, scopes) relying on Storage
and the service change happens automatically.
Edit:
I have forked the Plunker to highlight the problem. As you can see, the data in the upper part only updates because I manually call Storage.getItems()
again after the strategy has been changed. But I cannot do that, because other component - for example OtherController
- are also accessing data on Storage
and also need to automatically get their data from the new strategy. Instead, they stay bound to the initial strategy.
Javascript works on references. Your array items in app is same reference as items of strategyB items initially with the below statement and when you update the StrategyB items automatically items in your view gets updated(since same reference).
$scope.items = Storage.getItems();
So, when you switch strategy you are not changing the reference of items. It still points to StrategyB items reference.
You have to use the below mechanism to change the reference.
Then you can do something where you can communicate between controllers to change the items reference.
Please find the plunkr I have updated.
$rootScope.$broadcast("updateStrategy");
And then update your item list and others.
$scope.$on("updateStrategy",function(){
$scope.name = Storage.getName();
$scope.items = Storage.getItems(); //Here changing the reference.
//Anything else to update
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With