user1027169
user1027169

Reputation: 2867

Syncing data between controllers through a service

From this stackoverflow question, my understanding is that I should be using services to pass data between controllers.

However, as seen in my example JSFiddle, I am having trouble listening to changes to my service when it is modified across controllers.

angular.module('myApp', [])
    .controller('Ctrl1', function ($scope, App) {
        $scope.status = App.data.status;
        $scope.$watch('App.data.status', function() {
            $scope.status = App.data.status;
        });
})
    .controller('Ctrl2', function ($scope, App) {
        $scope.status = App.data.status;
        $scope.$watch('status', function() {
            App.data.status = $scope.status;
        });
})
    .service('App', function () {
        this.data = {};
        this.data.status = 'Good';
});

In my example, I am trying to subscribe to App.data.status in Ctrl1, and I am trying to publish data from Ctrl1 to App. However, if you try to change the input box in the div associated with Ctrl2, the text does not change across the controller boundary across to Ctrl1.

Upvotes: 5

Views: 4319

Answers (2)

gion_13
gion_13

Reputation: 41533

I agree with @shaunhusain, but I think that you would be better off using a factory instead of a service:

angular.module('myApp', [])
    .controller('Ctrl1', function ($scope, App) {
        $scope.localData1 = App.data;
    })
    .controller('Ctrl2', function ($scope, App) {
        $scope.localData2 = App.data;
    })
    .factory('App', function () {
        var sharedObj = {
            data : {
                status: 'Good'
            }
        };

        return sharedObj;
    });

Here are some information that might help you understand the differences between a factory and a service: When creating service method what's the difference between module.service and module.factory

Upvotes: 6

shaunhusain
shaunhusain

Reputation: 19748

http://jsfiddle.net/VP4d5/2/

Here's an updated fiddle. Basically if you're going to share the same data object between two controllers from a service you just need to use an object of some sort aside from a string or javascript primitive. In this case I'm just using a regular Object {} to share the data between the two controllers.

The JS

angular.module('myApp', [])
    .controller('Ctrl1', function ($scope, App) {
        $scope.localData1 = App.data;
})
    .controller('Ctrl2', function ($scope, App) {
        $scope.localData2 = App.data;
})
    .service('App', function () {
        this.data = {status:'Good'};
});

The HTML

<div ng-controller="Ctrl1">
    <div> Ctrl1 Status is: {{status}}
    </div>
    <div>
        <input type="text" ng-model="localData1.status" />
    </div>
<div ng-controller="Ctrl2">Ctrl2 Status is: {{status}}
    <div>
        <input type="text" ng-model="localData2.status" />
    </div>
</div>

Nothing wrong with using a service here but if the only purpose is to have a shared object across the app then I think using .value makes a bit more sense. If this service will have functions for interacting with endpoints and the data be sure to use angular.copy to update the object properties instead of using = which will replace the service's local reference but won't be reflected in the controllers.

http://jsfiddle.net/VP4d5/3/

The modified JS using .value

angular.module('myApp', [])
    .controller('Ctrl1', function ($scope, sharedObject) {
        $scope.localData1 = sharedObject;
})
    .controller('Ctrl2', function ($scope, sharedObject) {
        $scope.localData2 = sharedObject;
})
.value("sharedObject", {status:'Awesome'});

Upvotes: 10

Related Questions