Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit fa80a61

Browse files
committed
fix(ngBind): use same string representation as $interpolate
Fixes #11716 BREAKING CHANGE: `ngBind` now uses the same logic as $interpolate (i.e. {{myString}}) when binding, which means values other than strings are now transformed as following: - null / undefined become empty string - with an object's custom toString() function, except if the object is a Date, Array, or Number - otherwise with JSON.stringify Previously, ngBind would use always use toString(). The following examples show the different output: ```js $scope.myPlainObject = {a: 1, b: 2}; $scope.myCustomObject = {a: 1, b: 2, toString: function() {return 'a+b';}}; ``` Plain Object: ```html <!-- Before: --> <span ng-bind="myPlainObject">[object Object]</span> <!-- After: --> <span ng-bind="myPlainObject">{"a":1,"b":2}</span> ``` Object with custom toString(): ```html <!-- Before: --> <span ng-bind="myCustomObject">[object Object]</span> <!-- After: --> <span ng-bind="myCustomObject">a+b</span> ``` If you want the output of `toString()`, you can use it directly on the value in ngBind: ```html <span ng-bind="myObject.toString()">[object Object]</span> ```
1 parent a5fd2e4 commit fa80a61

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

src/ng/directive/ngBind.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ var ngBindDirective = ['$compile', function($compile) {
6060
$compile.$$addBindingInfo(element, attr.ngBind);
6161
element = element[0];
6262
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
63-
element.textContent = isUndefined(value) ? '' : value;
63+
element.textContent = stringify(value);
6464
});
6565
};
6666
}

test/ng/directive/ngBindSpec.js

+37
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,43 @@ describe('ngBind*', function() {
4646
expect(element.text()).toEqual('-0false');
4747
}));
4848

49+
they('should jsonify $prop', [[{a: 1}, '{"a":1}'], [true, 'true'], [false, 'false']], function(prop) {
50+
inject(function($rootScope, $compile) {
51+
$rootScope.value = prop[0];
52+
element = $compile('<div ng-bind="value"></div>')($rootScope);
53+
$rootScope.$digest();
54+
expect(element.text()).toEqual(prop[1]);
55+
});
56+
});
57+
58+
it('should use custom toString when present', inject(function($rootScope, $compile) {
59+
$rootScope.value = {
60+
toString: function() {
61+
return 'foo';
62+
}
63+
};
64+
element = $compile('<div ng-bind="value"></div>')($rootScope);
65+
$rootScope.$digest();
66+
expect(element.text()).toEqual('foo');
67+
}));
68+
69+
it('should NOT use toString on array objects', inject(function($rootScope, $compile) {
70+
$rootScope.value = [];
71+
element = $compile('<div ng-bind="value"></div>')($rootScope);
72+
$rootScope.$digest();
73+
expect(element.text()).toEqual('[]');
74+
}));
75+
76+
77+
it('should NOT use toString on Date objects', inject(function($rootScope, $compile) {
78+
$rootScope.value = new Date(2014, 10, 10, 0, 0, 0);
79+
element = $compile('<div ng-bind="value"></div>')($rootScope);
80+
$rootScope.$digest();
81+
expect(element.text()).toBe(JSON.stringify($rootScope.value));
82+
expect(element.text()).not.toEqual($rootScope.value.toString());
83+
}));
84+
85+
4986
it('should one-time bind if the expression starts with two colons', inject(function($rootScope, $compile) {
5087
element = $compile('<div ng-bind="::a"></div>')($rootScope);
5188
$rootScope.a = 'lucas';

0 commit comments

Comments
 (0)