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

Commit a5d804d

Browse files
danielkrainasNarretz
authored andcommitted
feat($interpolate): use custom toString() function if present
This behavior is consistent with implementations found in other languages such as Ruby, Python, and CoffeeScript. http://rubymonk.com/learning/books/1-ruby-primer/chapters/5-strings/lessons/31-string-basics https://docs.python.org/2/library/stdtypes.html#string-formatting-operations http://coffeescriptcookbook.com/chapters/strings/interpolation Fixes #7317 Closes #8350 BREAKING CHANGE: When converting values to strings, interpolation now uses a custom toString() function on objects that are not numbers or arrays (custom means that the `toString()` function is not the same as `Object.prototype.toString()`). Otherwise, interpolation uses JSON.stringify() as usual. Should you have a custom toString() function but still want the output of JSON.stringify(), migrate as shown in the following examples: Before: ```html <span>{{myObject}}</span> ``` After - use the `json` filter to stringify the object: ```html <span>{{myObject | json}}</span> ``` fixup
1 parent cd3673e commit a5d804d

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

src/ng/directive/input.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1290,6 +1290,9 @@ function createDateParser(regexp, mapping) {
12901290
}
12911291
});
12921292
return new Date(map.yyyy, map.MM - 1, map.dd, map.HH, map.mm, map.ss || 0, map.sss * 1000 || 0);
1293+
} else {
1294+
// If we fail to parse the string with the ISO regex, it might be because it's the result of Date.toString()
1295+
return Date.parse(iso);
12931296
}
12941297
}
12951298

@@ -1358,17 +1361,21 @@ function createDateInputType(type, regexp, parseDate, format) {
13581361
});
13591362
}
13601363

1361-
function isValidDate(value) {
1362-
// Invalid Date: getTime() returns NaN
1363-
return value && !(value.getTime && value.getTime() !== value.getTime());
1364-
}
1365-
13661364
function parseObservedDateValue(val) {
1367-
return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
1365+
if (val === '') {
1366+
return undefined;
1367+
} else {
1368+
return isDefined(val) && !isDate(val) ? parseDate(val) || undefined : val;
1369+
}
13681370
}
13691371
};
13701372
}
13711373

1374+
function isValidDate(value) {
1375+
// Invalid Date: getTime() returns NaN
1376+
return value && !(value.getTime && value.getTime() !== value.getTime());
1377+
}
1378+
13721379
function badInputChecker(scope, element, attr, ctrl) {
13731380
var node = element[0];
13741381
var nativeValidation = ctrl.$$hasNativeValidators = isObject(node.validity);

src/ng/interpolate.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,11 @@ function $InterpolateProvider() {
122122
value = '' + value;
123123
break;
124124
default:
125-
value = toJson(value);
125+
if (isFunction(value.toString) && value.toString !== Object.prototype.toString && !isArray(value)) {
126+
value = value.toString();
127+
} else {
128+
value = toJson(value);
129+
}
126130
}
127131

128132
return value;

src/ngMessageFormat/messageFormatCommon.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,24 @@ var noop = window['angular']['noop'],
1212
toJson = window['angular']['toJson'];
1313

1414
function stringify(value) {
15-
if (value == null /* null/undefined */) { return ''; }
15+
if (value == null) { // null || undefined
16+
return '';
17+
}
1618
switch (typeof value) {
17-
case 'string': return value;
18-
case 'number': return '' + value;
19-
default: return toJson(value);
19+
case 'string':
20+
break;
21+
case 'number':
22+
value = '' + value;
23+
break;
24+
default:
25+
if (isFunction(value.toString) && value.toString !== Object.prototype.toString && !isArray(value)) {
26+
value = value.toString();
27+
} else {
28+
value = toJson(value);
29+
}
2030
}
31+
32+
return value;
2133
}
2234

2335
// Convert an index into the string into line/column for use in error messages

test/ng/interpolateSpec.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,22 @@ describe('$interpolate', function() {
3535
expect($interpolate('{{ false }}')({})).toEqual('false');
3636
}));
3737

38+
it('should use custom toString when present', inject(function($interpolate, $rootScope) {
39+
var context = {
40+
a : {
41+
toString: function() {
42+
return 'foo';
43+
}
44+
}
45+
};
46+
47+
expect($interpolate('{{ a }}')(context)).toEqual('foo');
48+
}));
49+
50+
it('should NOT use toString on array objects', inject(function($interpolate) {
51+
expect($interpolate('{{a}}')({ a: [] })).toEqual('[]');
52+
}));
53+
3854

3955
it('should return interpolation function', inject(function($interpolate, $rootScope) {
4056
var interpolateFn = $interpolate('Hello {{name}}!');

0 commit comments

Comments
 (0)