0

I think I just lost some hours to the dot-notation in AngularJS.

This Plunker demonstrates the problem which still irritates me:

app.controller('MainCtrl', function($scope, ValueService) {
$scope.obj= ValueService.getObject(); // Output: {"string": "New!!!"}
$scope.val = ValueService.getVal(); // Output: "init"
ValueService.setVal();

})
.service('ValueService', function(){
var output= {string: 'init'};

this.setVal = function(val){
output.string = 'New!!!';
};

this.getObject = function(){
return output;
};

this.getVal = function(){
return output.string;
};

return this;
});

I did know that i should use objects when using ng-model (the dot-notation helps resolving reference issues when searching nested scopes). However I was not aware that this applies to a simple case like this as well. I was even more surprised because the reference to my object stays in tact if i use arrays (and modify it with push/splice): another Plunker

Could someone explain why exactly the databinding does not work for the value anymore when i reassign it? Is there a way to actually bind to the value without passing a wrapper-object from the service?

Jai
  • 74,255
  • 12
  • 74
  • 103
H W
  • 2,556
  • 3
  • 21
  • 45
  • 1
    Create a plunker which shows that the binding is not working when you reassign. Then we can help. – ashfaq.p Feb 11 '16 at 14:01
  • OP has already posted a link look for _another Plunker_ link. – Jai Feb 11 '16 at 14:05
  • The link to "another Plunker" might be more clear, but in fact the call to `setVal()` in the first Plunker is already a reassignment that is not caught by `$scope.val` – H W Feb 11 '16 at 14:13

2 Answers2

2

This is because whenever you return an object from a function in Javascript, you are actually returning a reference to an object. In your example

this.getObject = function(){
    return output;
};

the reference to object is returned. And any changes made to this reference will reflect in the actual object and that is why the data binding works for this.

Whereas, when you return a string from a function, you are returning the value, not the reference to the actual string.

this.getVal = function(){
    return output.string;
};

Here you are returning a string when you return output.string which has value "init". Any modification done to object.string is not going to change the returned string anymore and that is why it the data binding is failing for value.

See this answer for more information.

Community
  • 1
  • 1
hallucinations
  • 3,424
  • 2
  • 16
  • 23
  • Please reconsider your answer and take my link "another Plunker" into account. There you see that objects and strings behave identically - they both loose the reference when you reassign them. – H W Feb 11 '16 at 14:24
  • @HW, Sorry, I had given a wrong link. I've corrected the link in my answer now. See example 4 in that answer, you will be clear on how overwriting an object inside a function loses its actual reference. – hallucinations Feb 11 '16 at 14:37
0

the function getVal returns the value of output.string AT THAT POINT IN TIME. you then assign this value to your variable $scope.val. so at that point in time output.string is "Init" hence the value of $scope.val is "Init" This will never change, why would it ? This has nothing to do with angularjs 2-way data-binding or dot notation. You simply assign the value "Init" to $scope.val and never change it again, this is a pure javascript-thing going on here.

Patrick Kelleter
  • 2,631
  • 1
  • 13
  • 19
  • Okay, so this is a really simplified example. In my original code the "string" is an object as well and it behaves the same. I really think it is rather an issue with object references than the difference between strings and objects. – H W Feb 11 '16 at 14:26
  • my answer also applies if for output.foo, foo is an object instead of a string, yes. so what exactly is your question ? if you replace the variable you returned completely then the other side will not recognize this change because you create a new variable. this has nothing to do with angular, its a javascript thing. if you replace the variable INSIDE of an object your returned then the other side can recognize these changes and depending on the circumstances angular will recognize this automatically and update the views (not always however, it depends on the code) – Patrick Kelleter Feb 11 '16 at 14:45