0

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 ?

2
  • you can use service and $broadcast Commented Feb 26, 2016 at 10:53
  • I found this example with $broadcast in google: jsfiddle.net/VxafF Commented Feb 26, 2016 at 10:54

3 Answers 3

1

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
});
Sign up to request clarification or add additional context in comments.

Comments

0

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);
            }
        }
    };
});

Comments

0

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 Solution

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 Solution

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.