lavender
lavender

Reputation: 67

Change in AngularJS factory return value not reflected

https://plnkr.co/edit/hccJqwtDlqcOBhxnwZ94?p=preview

In this example when the factory return value changes in $timeout, the scope variable which points to the factory (in this case anotherVar) reflects the change but the variable that points the specific property (var) does not.

// Code goes here

angular.module("sample",[])
 .controller("myctrl",function($scope,TestService){
    $scope.var = TestService.name;
    $scope.anotherVar = TestService;
    })
.factory('TestService',function($timeout){
    var ret = {};
    ret.name = "temporary";
    $timeout(function() {
        ret.name = "final";
    },4000);
    return ret;
    
});
<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.6.6" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="sample" ng-controller="myctrl">
    <h1>Hello Plunker!</h1>
    Value: {{var}} <br>
    Another Value : {{anotherVar}}
  </body>

</html>

Upvotes: 0

Views: 334

Answers (2)

IsraGab
IsraGab

Reputation: 5185

Is not specific to angular, but with javascript, and the diffrence between pass by reference or pass by value (known in almost all of programming languages).

When you assign a variable:

var a = 3;
//then
var b = a;
// here you'expecting that b == 3, isn't it?
// well you're right!

//now let's do the following:
b = 5;
// are you expecting to see 5 into a (because b=a)?
// well, a == 3

Because the a variable was a primitive value so the affectation (b = a) was a pass by variable (=only the variable of a was set into b).

If you try now to pass by reference (using object):

var a = {}; // define a as an object
a.a = 3; // a get a property a and its value is 3

var b = a; // now the affectation is an object (=pass by reference)
// we are not assigning the value of a but its reference.

if you're changing the a property inside the b object: b.a = 5?

now if you look at the a object, you will see that a.a = 5

And that the reason of the behavior you have in you factory.

Angular factories are objects.

You are returning the object TestService

but your $scope.var is assigned to a primitive value (TestService.name), so when that value is changed it won't be reflected in your $scope.var.

In the second line an object is assigned (TestService), so if a property inside of this object chenged it will be reflected, because it is the SAME OBJECT.

To summarize:

  • Assign a value it is only the value that is assigned, if value of a changes you won't see it on b variable (because that 2 distinct variables)
  • Assign by reference says that a and b are actually the SAME object. if one of their properties change you will see it in the other variable

Upvotes: 0

P. Best
P. Best

Reputation: 21

Your first variable, var, has already been set based on the return value from the first factory call. Since it's scoped to the controller myCtrl, it isn't going to look elsewhere for changes.

Your second variable, anotherVar, is scoped to the factory, so the update in your $timeout() is reflected.

You can read more about AngularJS scope here.

Upvotes: 1

Related Questions