Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 687
user1027169 Avatar asked Dec 06 '13 22:12

user1027169


2 Answers

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'});
like image 119
shaunhusain Avatar answered Oct 20 '22 07:10

shaunhusain


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

like image 31
gion_13 Avatar answered Oct 20 '22 08:10

gion_13