-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Interpolation should call toString on objects #11406
Comments
I don't think Angular should do that - you would get some weird behavior happening if it did that on objects. For example, here is some of the undesired behavior one might get if this was supported: var foo = {}; foo.toString() // yields '[object Object]' {} + '' // yields 0 These two examples would be strong arguments against supporting this IMO. I would rather Angular fail silently in those two cases. For your case, you could always create a custom filter to format it as desired. |
Right now angular shows "{}" for the above example. That's not even weirder than calling toString()? Current behavior is silly. Let's improve it. Throw a useful error, or call "toString", or concat with a string, but don't just show curlies or enter into an infinite loop... |
Also: |
Hi, there is always a constant struggle between
In most cases, the answer is a balance. We needs to be flexible and at the same time let developers know when there is something that is not supported/will not work. On top, semver rules should be followed for breaking changes. With this in mind, I find the behavior to be acceptable. Now if the consensus is that calling |
If this is a breaking change then semver means it has to wait until 2.0. :( |
But thanks for getting back. I can definitely appreciate the bind you guys are in and it's easy to think that something is the right way just because it makes sense to me, but that is obviously not always the case. |
👍 This should be the expected behavior. @wesleycho if you dont want to see |
@yordis a developer should not have to monkeypatch |
@wesleycho Is that monkeypath? Why? For me it's prototype inheritance. If you know the object have to output something different than the normal output, you just override the function. _Why don't use the flexibility of the language_, developers need to know what they are doing. If you are a javascript developer and you know how the toString is used it in Javascript there is not problem.
What's wrong with this. function Person (firstname, lastname) {
this.firstname = firstname;
this.lastname = lastname;
}
Person.prototype.toString = function() {
return this.firstname + ' ' + this.lastname;
}
var me = new Person('Yordis', 'Prieto');
Person.toString() //function Person (firstname, lastname) { this.firstname = firstname; this.lastname = lastname; }
me.toString() // "Yordis Prieto" function you() {}
var fo = new you()
you.toString() // "function you() {}"
fo.toString() // "[object Object]" I am programming in Ruby using RoR and you see a lot of Ruby extension from RoR making the language even better. I said this because we put too many limitations to Javascript making us full depended of browser providers. I am telling you that because the monkeypatch thing call my attention. The prototype inheritance is there, use it! |
I think it should call the toString() method. If the $parse service doesn't call toString() method, what does it call? |
This came up for me the other day and I can get around it. But since the issue has been placed in the Ice Box, I must point out that stringification/interpolation of numbers and strings does not produce quoted strings which means strings at least are not being JSONified. Furthermore, as has been pointed out, ng-bind is not consistent with interpolation markup just as interpolation markup is not consistent with Javascript itself. All objective languages I've worked with, such as C#, Java, Perl, PHP, and Javascript, provide a method called to return the string representation of the object when that object is stringified/interpolated. AngularJS is stepping outside this widely used standard for reasons I cannot determine. As the 2.0 release is fast approaching, this issue should be addressed before more problems with Angular's stringification/interpolation inconsistency with industry standard are discovered. Since this appears to be a known problem such that everyone is already having to use filters to overcome the default stringification of interpolated objects as serialized JSON, It may not be such a breaking change. |
The reason it that Admittedly, it doesn't work so well for |
Thank you for responding, @gkalpak. No, there is no need to do anything on my part. Like everyone else, I'm using a filter to render the stringified date. The default output of JSON.stringify() (where an object has not provided a toJSON() method), is to return a string of the object serialized as JSON. I find it hard to believe this is any more useful than "[object Object]" for the purposes of interpolation. ng-bind renders an object by calling the toString() method, not toJSON() or JSON.stringify(). Given your comment that "[object Object]" is not a useful value, why is it okay with ng-bind and not with interpolation markup? Given the prolific nature of date values in web based applications, I would expect a Date object to be used in interpolation quite often. At least, we certainly use it often and it is much easier than moving strings around especially if you might want to do some date arithmetic. I would assume Date objects are used in interpolation more than you might think and everyone else is using filters like I am. Having worked with all the languages you mention quite extensively, I know that both C# and Java, being strongly typed languages, may error when an Object is passed where a String is expected. There are some cases where an object can be provided where a string is expected but the Object.toString() method is called to render the object as a string. Java, PHP, and Perl all provide object stringification methods as toString(), __toString(), and stringify(), respectively. These methods are called anytime an object is stringified/interpolated. I did not open this issue and probably would not have given I don't make a habit of telling people how to code unless they work for me. But I strongly recommend this issue is moved out of the IceBox and considered before 2.0 is released. Automatic stringification of Javascript objects provides great flexibility and is blocked by a feature of AngularJS that has little value to the end user. |
Except on Numbers, Dates and Arrays. Thanks to @danielkrainas for the initial implementation of this feature. 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 The commit also exposes a private $$stringify method on the angular global, so that ngMessageFormat can use the same logic without duplicating it. Fixes angular#7317 Closes angular#8350 Fixes angular#11406 BREAKING CHANGE: When converting values to strings, interpolation now uses a custom toString() function on objects that are not Number, Array or Date (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> ```
What is the status of this PR, I believe it is merged into master branch... but I am getting he inconsistent results when interpolating the object, sometime getting full object some time getting for example
Originally posted by @shmdhussain in #14715 (comment) |
The string value is what is going to be used in the rendering of the information, but this doesn't seem to be respected.
http://plnkr.co/edit/ZLmiavC9lSlKj1b6cQJk?p=preview
For a real-world use-case: We'd like to return goog.Uri instances from our controller and have angular appropriately format them in the template, but it doesn't work -- it seems like the uri instances are compared by identity instead of string value (even though only string value will affect what the user sees), which I think was causing infinite loops. In the plunkr above I cannot get the right information to show up without manually stringifying first.
Right now our workaround is to call
toString()
or+ ""
manually within the controller, but this is just visual noise... it also is incentive to pass around strings instead of js objects, which I think would obscure the intent of the code.The text was updated successfully, but these errors were encountered: