I have created a plunker to test binding $scope
on services. And I found that I can only bind to primitive values but reference values of a service.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>
<body ng-app="BindToService">
<div ng-controller="BindToServiceCtrl as ctrl">
// I wonder why I could only bind on reference but primitive values of a service.
counterFactoryObj: {{counterFactoryObj}}<br/>
counterFactoryVal: {{counterFactoryVal}}<br/>
counterFactoryFun(): {{counterFactoryFun()}}<br/>
</div>
<script type="text/javascript">
var app = angular.module("BindToService", []);
app.controller("BindToServiceCtrl", function ($scope, CounterFactory) {
$scope.counterFactoryObj = CounterFactory.obj;
$scope.counterFactoryVal = CounterFactory.val;
$scope.counterFactoryFun = CounterFactory.fun;
});
app.factory("CounterFactory", function ($interval) {
var obj = [0];
var val = 0;
var fun = function () { return val; };
var addCounter = function () {
obj[0] += 1;
val += 1;
};
$interval(addCounter, 1000);
return {
obj: obj,
val: val,
fun: fun
};
});
</script>
</body>
In this demo, only counterFactoryObj
and counterFactoryFun()
change by time. I wonder how AngularJS binds values.
There are a few things here that I think are causing confusion.
First, when you return an object with:
the property
val
of the object is set at the time you return it to whatever the value was ofsomeVal
. So, when you return yourCounterFactory
service,CounterFactory.val === 0
- always - and it's not related to Angular's binding.Second, with
CounterService
service, yourCounterService
instance hasthis.val
and in fact it is being updated with $interval (try it withconsole.log
). The problem there is that you assign its value in a particular point in time (e.g. when controller function runs) to the$scope.counterServiceVal
variable. Here, althoughCounterService.val
changes, the following remains true:$scope.counterServiceVal === 0
.Btw, both
.service
and.factory
return a singleton service instance as far as Angular is concerned, except in one your return a new-able Function and in the other - the actual instance, but that is just related to what Angular does to obtain the actual service instance - after the service is injected it behaves the same way.And, finally, if you want to bind to a value - you can, but you need to actually change that value and bind to that changing variable. Here's how you'd do this with your
CounterFactory
, as an example: