Are there any general rules of thumb for sharing data between controllers?
I've seen 2 types of answers to how to accomplish this:
I'm not sure when it is best to use one approach over the other.
Moreover, there is 1 thing I really don't like about approach #1. Here is a toy-example taken from some real code:
angular.module('profileService', [])
.factory('profileService',
[
function() {
var selectedProfile = { profileId: null };
return {
getProfile: function(profileId, callback) {
// marshall ajax request into format server will know how to handle
// ajax call to server
// marshall ajax response into format UI (controller) will know how to handle
},
createProfile: function(callback) { ... // ajax call to server ... },
updateProfile: function(callback) { ... // ajax call to server ... },
deleteProfile: function(callback) { ... // ajax call to server ... },
getSelectedProfile: function() {
return selectedProfile.profileId;
},
setSelectedProfile: function(profileId) {
selectedProfile.profileId = profileId;
},
};
}
]);
This seems to be poor design. The service (as is most of our services) exists to translate and make requests to/from the server. Most of our services are completely stateless. It is trivial to inject mock services for testing, etc...
But now all of a sudden our service has state. This just seems like a bad idea.
An alternative approach might be to build a service that exists solely for sharing data between controllers (and never makes backend calls), but this isn't all the appetizing either. It smells like a service providing a global namespace which doesn't seem like great design.
Just wondering, are there any thoughts about approach #1 vs #2. Is containing state in a service not necessarily a bad thing? Are events a better approach to sharing state?
Thanks.
The official AngularJS guide for controllers recommends the use of services for sharing state:
Do not use controllers to:
- Share code or state across controllers — Use angular services instead.
Using services to share data/state is fine (webcam.isStreaming, socket.isConnected, etc), but things like the "selection" don't belong in the profileService, it should for example be possible to have multiple selections.
Events are not for sharing state, they are for ... events. like "includeContentLoaded", "webcamReady", "socketMessage", etc. A controller might not be ready (loaded async via ng-include) and miss an event.
Method 3: Have you tried the UI Router yet? it is organized around states.
You can use $stateParams or resolve
to pass the selected profile.
Some of it is also possible with ngRoute, but very limited.
Method 4: You can use the $scope
to share data between parent and child controllers.
A benefit/downside is that selection lifetime is connected to the scope.
This creates some coupling/complexity, but not more than a profileSelectionsService would.
Works great if the parent controllers writes to the $scope and child controller reads.
It gets tricky when both controllers want to write to the $scope
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