Let's say I'm using a class (acting more like a kind of struct) representing a string value, with the side-effect that it changes its value every time you access it:
function Foo() {
var value = 'a';
this.getValue = function() {
if (value == 'a') {
value = 'b';
return 'a';
}
else {
value = 'a';
return 'b';
}
}
}
..and I override it's toString() method:
Foo.prototype.toString = function() {
return this.getValue();
}
Outputting this value is fine with a direct reference:
var foo = new Foo();
alert(foo); //a
document.getElementById('bar').innerHTML = foo; //b
However, outputting the object with an AngularJS expression results in {} being displayed rather than the toString()/getValue() value:
var foo = new Foo();
var app = angular.module('main', []);
app.controller('ctrl', function($scope) {
$scope.val = foo;
alert($scope.val); //a (has not been changed by previous line)
});
..and then:
<div ng-app="main" ng-controller="ctrl">{{val}}</div> //{} (rather than b)
I could just use $scope.val = foo.getValue();, $scope.val = foo.toString(); or even $scope.val = foo + '';, and according to Is it possible to provide an implicit way of converting object into string for angular templates? ng-bind calls the toString() method, but why is it not called when Angular evaluates the object in an expression?