Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my angular service value not updating my scope?

Tags:

angularjs

I have this simple jsfiddle that demonstrates what I thought would be a dynamic service value that could be monitored by any controller into which it was injected. Here is the angular code:

var app = angular.module("application", []);

app.service("valueSetter", function(){
    that = this;
    this.serviceValue = {count: 1};
    this.updatevalue = function(){
        that.serviceValue.count = that.serviceValue.count + 1;
        console.log(that.serviceValue);
    };
});

app.controller("appcontroller", function($scope, valueSetter){
    $scope.scopeValue = valueSetter.serviceValue.count; 
    $scope.update = function(){
        valueSetter.updatevalue();
    };
});

and the html is simple:

<div ng-app="application" ng-controller="appcontroller">    
    Scope value is: {{scopeValue}}<br /><br />
    <input type="button" value="update" ng-click="update()" />
</div>

If you watch the console, you can see the service value increment, but the incremented value is not reflected in the controller scope. Am I misunderstanding how this should be working?

like image 393
sonicblis Avatar asked Jun 21 '14 01:06

sonicblis


1 Answers

You can't bind to a service variable like that, but you can bind to a service function. Add a getter to your service:

this.getValue = function(){
    return that.serviceValue;
}

Assign scopeValue in the controller to the getter:

$scope.scopeValue = valueSetter.getValue; 

Bind like this:

Scope value is: {{scopeValue()}}

Edit

You can also assign your valueSetter service to a $scope variable in the controller:

$scope.valueSetter = valueSetter;

And bind like this:

Service value is: {{valueSetter.serviceValue}}

Demo

Edit 2

You can also change this.serviceValue in the service to be an object, like this:

this.serviceValue = {value: 1};
this.updatevalue = function(){
    that.serviceValue.value = that.serviceValue.value + 1;
    console.log(that.serviceValue.value);
};

In your controller, assign scopeValue like this:

$scope.scopeValue = valueSetter.serviceValue; 

And then bind like this:

Scope value is: {{scopeValue.value}}

Demo

The point is that if the property in the service is a primitive (essentially a string, number, or boolean), when you assign it to a scope variable, you're just making a copy of the value, and it has no link back to the service. If the service property is an object, then when you assign it to a scope variable, you're copying the reference to the service property, which gives you the binding you are looking for.

like image 106
Jerrad Avatar answered Nov 09 '22 04:11

Jerrad