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> ```
This commit is contained in:
@@ -60,7 +60,7 @@ var ngBindDirective = ['$compile', function($compile) {
|
||||
$compile.$$addBindingInfo(element, attr.ngBind);
|
||||
element = element[0];
|
||||
scope.$watch(attr.ngBind, function ngBindWatchAction(value) {
|
||||
element.textContent = isUndefined(value) ? '' : value;
|
||||
element.textContent = stringify(value);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,6 +46,43 @@ describe('ngBind*', function() {
|
||||
expect(element.text()).toEqual('-0false');
|
||||
}));
|
||||
|
||||
they('should jsonify $prop', [[{a: 1}, '{"a":1}'], [true, 'true'], [false, 'false']], function(prop) {
|
||||
inject(function($rootScope, $compile) {
|
||||
$rootScope.value = prop[0];
|
||||
element = $compile('<div ng-bind="value"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toEqual(prop[1]);
|
||||
});
|
||||
});
|
||||
|
||||
it('should use custom toString when present', inject(function($rootScope, $compile) {
|
||||
$rootScope.value = {
|
||||
toString: function() {
|
||||
return 'foo';
|
||||
}
|
||||
};
|
||||
element = $compile('<div ng-bind="value"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toEqual('foo');
|
||||
}));
|
||||
|
||||
it('should NOT use toString on array objects', inject(function($rootScope, $compile) {
|
||||
$rootScope.value = [];
|
||||
element = $compile('<div ng-bind="value"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toEqual('[]');
|
||||
}));
|
||||
|
||||
|
||||
it('should NOT use toString on Date objects', inject(function($rootScope, $compile) {
|
||||
$rootScope.value = new Date(2014, 10, 10, 0, 0, 0);
|
||||
element = $compile('<div ng-bind="value"></div>')($rootScope);
|
||||
$rootScope.$digest();
|
||||
expect(element.text()).toBe(JSON.stringify($rootScope.value));
|
||||
expect(element.text()).not.toEqual($rootScope.value.toString());
|
||||
}));
|
||||
|
||||
|
||||
it('should one-time bind if the expression starts with two colons', inject(function($rootScope, $compile) {
|
||||
element = $compile('<div ng-bind="::a"></div>')($rootScope);
|
||||
$rootScope.a = 'lucas';
|
||||
|
||||
Reference in New Issue
Block a user