-
Notifications
You must be signed in to change notification settings - Fork 27.4k
One-time binding doesn't work with filters #8605
Comments
I created a plnkr and can't reproduce the issue in Chrome. What version of Angular are you using, and in what browser are you seeing this issue? |
plnkr is so slow. To repro:
Without "::" the new value is properly processed by filter and bound to the element. Then add "::" to see the element become empty. |
I'm pretty sure the reason for this is that the filter is not returning |
Yep, numberFilter returns the empty string if the input value is null or undefined. This doesn't really strike me as wrong per se, you could just write another filter that uses the number filter if the value is not undefined (the way one-time binding works is, it stops watching as soon as the value becomes something that is not undefined. But even if it worked the way the original prototype worked, where it watches until the value stabilizes, this would still not do what you want. Sorry!) |
I believe Caitlin is right. However, rewriting all built-in filters to support one-time binding probably should be done in Angular, rather than be done by all users repeatedly. |
There's no way for a filter to know if you are expecting the value to be one-time bound or not, unless we add a new flag or something, which is not likely to happen, and even if it did, you'd still have to tell the filter that's what was going on. We could change the parser to not evaluate filters if the value is one-time bound and still undefined, but until we do that, this is really working as expected. That might be a complicated change :( |
Since Angular expressions are forgiving, wouldn't it make sense for filters to return undefined instead of empty string when input is undefined or null? Thus, filters will work for both persistent and one-time bindings. |
I mean we could do that, but it would be a breaking change --- you'd get the same issue with all of the builtin filters though, if we get I really think a better solution would be to make the parser somehow aware that it doesn't need to invoke filters if the input is undefined and it is using one-time binding, that would require less work in core and user-created filters |
Ok, here is an updated plunker: http://plnkr.co/edit/i6teCiKAe32c002IxrqV?p=preview |
how about we say that all filters are pure (and stop associating state with them like ngLocale), and change the parser to not evaluate them when a value hasn't changed! okay maybe that's unrealistic for 1.x :( |
@caitp you are right, this would be the best option, but not feasible for 1.x I vote against not invoking the filters in 1.x in the special case where the input is |
we could skip reevaluation of filters for primitive values, that would for objects/arrays we can't skip because we'd need to setup a deep watch On Wed, Aug 27, 2014 at 3:56 PM, Tobias Bosch [email protected]
|
What would we do if a filter isn't used at the end of the expression, but in the middle, like: ng-change="callback({ key: (value | number) })" |
that works by accident and not by design :) On Thu, Aug 28, 2014 at 10:52 PM, Rodric Haddad [email protected]
|
I went through all the core filters and only number and currency filter are affected by this issue - both share a helper formatting fn that returns the empty string instead of undefined. all other filters pass through the value if the value is not of the type that the filter is designed to handle. |
When these special values are passed through one-time binding will work correctly. BREAKING CHANGE: previously the currency filter would convert null and undefined values into empty string, after this change these values will be passed through. Only cases when the currency filter is chained with another filter that doesn't expect null/undefined will be affected. This should be very rare. This change will not change the visual output of the filter because the interpolation will convert the null/undefined to an empty string. Closes angular#8605
When these special values are passed through one-time binding will work correctly. BREAKING CHANGE: previously the number filter would convert null and undefined values into empty string, after this change these values will be passed through. Only cases when the number filter is chained with another filter that doesn't expect null/undefined will be affected. This should be very rare. This change will not change the visual output of the filter because the interpolation will convert the null/undefined to an empty string. Closes angular#8605
When these special values are passed through one-time binding will work correctly. BREAKING CHANGE: previously the currency filter would convert null and undefined values into empty string, after this change these values will be passed through. Only cases when the currency filter is chained with another filter that doesn't expect null/undefined will be affected. This should be very rare. This change will not change the visual output of the filter because the interpolation will convert the null/undefined to an empty string. Closes angular#8605
When these special values are passed through one-time binding will work correctly. BREAKING CHANGE: previously the number filter would convert null and undefined values into empty string, after this change these values will be passed through. Only cases when the number filter is chained with another filter that doesn't expect null/undefined will be affected. This should be very rare. This change will not change the visual output of the filter because the interpolation will convert the null/undefined to an empty string. Closes angular#8605
When these special values are passed through one-time binding will work correctly. BREAKING CHANGE: previously the number filter would convert null and undefined values into empty string, after this change these values will be passed through. Only cases when the number filter is chained with another filter that doesn't expect null/undefined will be affected. This should be very rare. This change will not change the visual output of the filter because the interpolation will convert the null/undefined to an empty string. Closes #8605 Closes #8842
I came across even weirder behavior... when used filter that returns "random" output on one-time binding, it broke ALL the instances of one-time bindings in the scope |
@stryju one time binding or not a given expression needs to stabilize. Your filter makes it so the model never stabilizes hence the error. |
Try something like this: http://plnkr.co/edit/QogrC0bOvX8EYnmQOhpf?p=preview |
@pkozlowski-opensource ah, good to know - thanks @caitp 👍 thanks! |
@caitp I have different kind of issue with custom filters those are returning I am using AngularJS version - |
@Sojiro I think that makes sense? Angular considers anything that's not undefined as a "stable" value: https://code.angularjs.org/1.5.8/docs/guide/expression#one-time-binding |
This works fine:
This works fine too:
But this renders an empty div:
The text was updated successfully, but these errors were encountered: