Reputation: 1338
I want to pass some data from one controller to a second one via an onClick
-Event. I tried to use a service between the two controllers but it seems that the controller who receives the data from the service doesn't recognize the onClick
-Event of the first controller which leads to static/non changing data.
OnClick
function (Controller 1)
$scope.select = function(index){
vm.currentActive = index;
sessionService.setState(index);
};
Exchange service
app.service('sessionService', function() {
var state = null;
var setState = function(changestate){
state = changestate;
};
var getState = function(){
return state;
};
return {
setState: function(changestate){
setState(changestate);
},
getState: function(){
return state;
}
};
});
Receiving Controller (Controller 2)
app.controller('ContentController', function ($scope, sessionService)
{
var vm = this;
vm.currentActive = sessionService.getState();
});
In the end I want that the state of Controller 2 changes whenever the OnClick
-Event is triggered in controller 1. Is this way with the service the best or what do recommend to change the data in controller 2 after a click ?
Upvotes: 0
Views: 114
Reputation: 49714
The reason your Receiving Controller is not getting the updated value is because the state
property is copied into vm.state
at the point of the directive definition object's initialization.
vm.currentActive = sessionService.getState();
Here, getState
is only called once, so it won't matter if that state
value is later updated...
One option would be to call getState
from the controller's view (which will get re-called (i.e. the value will be updated) with every digest cycle)...note this strategy has performance implications...
Another option is to leverage the trickle down effect of referenced objects (or as Miško explains in this Angular Best Practices video, "...if you don't have a dot, you're doing it wrong..."
You could utilize this strategy by using an object to store the state in your Exchange Service...
app.service('sessionService', function() {
var data = {};
var setState = function(changestate){
data.state = changestate;
};
var getState = function(){
return data.state;
};
return {
setState: setState,
data: data
};
});
Receiving Controller
app.controller('ContentController', function ($scope, sessionService) {
var vm = this;
vm.data = sessionService.data;
});
Then whenever data.state
is updated in sessionService
, vm.data.state
will (by virtue of referenced data) contain the updated data as well.
In other words, vm.data.state
will always contain the most up to date value of sessionService.data.state
because they both refer to the same object.
Upvotes: 0
Reputation: 2167
One option for watching the state of a service is to use $scope.$watch
with a function that returns the value to be watched for changes.
$scope.$watch(function(){ return sessionService.getState(); }, function(newValue, oldValue){
//Do something
});
If the value in the service is changed, the watch will pick up the change on the next digest cycle. With this method there's no need to have your service or other controller try and signal that the value has changed.
If your service's getter method does not depend on this
, you can simplify the watcher by just passing the getter method as the watch function rather than using a wrapper function.
$scope.$watch(sessionService.getState, function(newValue, oldValue){
//Do something
});
Upvotes: 1
Reputation: 66490
You can add onChange event to service:
app.service('sessionService', function() {
var state = null;
var callbacks = [];
var setState = function(changestate) {
callbacks.forEach(function(callback) {
callback(state, changestate);
});
state = changestate;
};
var getState = function() {
return state;
};
return {
setState: function(changestate) {
setState(changestate);
},
getState: function() {
return state;
},
onChange: function(fn) {
if (typeof fn == 'function') {
callbacks.push(fn);
}
}
};
});
Upvotes: 0