-
Notifications
You must be signed in to change notification settings - Fork 27.3k
feat(ngModel): bind to getters/setters #7991
Conversation
|
you are doing a good job 👏 |
|
@IgorMinar @caitp @matsko – feedback pls. I prefer not to introduce new syntax for the reasons stated above. I'm worried that btford@fa4b121#diff-c244afd8def7f268b16ee91a0341c4b2R1810 might have performance implications. |
|
the main thing I'm not big on here is the fact that it's specific to forms/ngModel, but maybe it doesn't matter that much. Adding new syntax to the parser would generalize this more, but that's understandably not something we necessarily want to do. I don't think there should be a major performance hit from the type checks because those strings should be interned and most likely reduced to a pointer comparison, but I could be wrong. Branching might not be super helpful, but it probably won't matter in this case. I have some questions though, comments forthcoming |
src/ng/directive/input.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was going to ask what we're doing with getter here, because getter(ctrl.$modelValue) doesn't use the result for anything.
But I realized that this is because this is named getter, and it should really be renamed to reflect how it's being used here --- setter or getterSetter maybe
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Agreed on the var name
I think this is reasonable. The main use case I want to address with this approach is where currently you have to write a |
|
I don't have a lot against it, but I think all of these concerns would be lifted if it was implemented as a syntax enhancement in the parser instead. But I don't have any major concerns with shipping it as is |
|
What kind of syntax are you thinking? |
|
I don't have anything in particular in mind, but it would have to clearly indicate that the method should be treated as a getter/setter
I'm not sure --- it doesn't really matter how it would look, so long as it doesn't conflict with other uses, I guess. But it's harder to implement this way, so I don't have major reservations about landing it as is. |
|
@IgorMinar your input would be appreciated! |
src/ng/directive/input.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just use isFunction here
|
instead of syntax change, how about we add a new ngModelOption option that would specify that the model is a getter/setter? that way there is no perf impact, no confusion, everyone is happy it just requires a bit more typing which should however not be that big of a deal especially given that we are trading it off for less confusion/surprises? |
|
What about my proposed behavior by default, or you can explicitly provide a Then there is no ambiguity and by default much less typing for users who want this behavior. |
|
Since ngModelOptions can be inherited from the form you'd need to specify On Fri, Jun 27, 2014, 5:22 PM, Brian Ford [email protected] wrote:
|
|
I don't think it's worth worrying about those cases I mentioned until someone actually complains about them, but if you want to add such a solution, it probably doesn't hurt to try it |
|
Hmm. On a semi-related note, there are 3 possible behaviors for any given
See my gross WIP patch above for clarification. I added a new option, |
|
We decided that the first case in my comment above wasn't ever really desirable. We'll keep the current behavior as a default and expose the new behavior via |
|
I've implemented the changes as described, but I'd like to improve the documentation (and commit message) around this before it's merged. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you should also add a test for the default behavior
|
add the missing default case test + docs and ship it :) |
|
okay 🍓 |
|
Done; I'm planning to merge this by EoD unless anyone has additional feedback. |
src/ng/directive/input.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really understand what external API means here. Server-Side? Exposed in view?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good call. I like "exposed to the view" better.
|
@Narretz: I addressed your comments. Thanks for the feedback! |
src/ng/directive/input.js
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't be this { getterSetter: true }?
Same on next line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 Good catch!
|
Landed as b9fcf01. |
|
@btford this is a great feature but I would like the option to support different types of getters and setters. Not every getter is avalaible as where if What do you think? |
|
This is nice, but here is a subtle bug: if you provide This is inconvenient when using function factories, e.g. in the following example But given the non-assignable limitation, this does not work. |
|
I feel like trying to support all of these cases (functions returned from other functions returned from other functions and other matryoshka-like behaviour) is not going to be helpful --- I think you could instead use patchMethod when defining your getter/setter to begin with, but there's no point asking ngModel to get the getter/setter by calling it. ngModel already cares about too much stuff already, it would be crazy to give it more things to be concerned with :( Personal opinion, and maybe Brian or others disagree, but I see this as a kind of feature creep, and would prefer if the limitations were documented and solutions prescribed, rather than adding more hacks to ngModel. |
|
I'm not convinced that the case in @ntrrgc's example is a particularly good idea. |
|
Is it possible in angular 1.2? Missing support of object.defineProperty in IE8 and dropping support of IE8 in angular 1.3 makes ugly without getter setter support |
This feature is not backported to 1.2 by design because it is a breaking change. If you know what you are doing, you could decorate |
Currently, you might do this if you want to bind to getters/setters:
The implementation in this PR changes the semantics of
ngModelin the following ways:If the expression bound to
ngModelresolves to a function, the function is invoked to get the current value to be expressed in the DOM. When the binding changes, if the expression bound tongModelresolves to a function (at that time) the function is invoked with the new value.This means instead, you could do this:
I like that to end developers, this feels like "uniform access" for common cases. I don't like that this means there's a difference in semantics between
ngModeland expressions elsewhere in Angular.This would be a breaking change, but I don't think that this would affect any legitimate use cases. The only case I can think of is if hypothetically, you bind to some property that's originally a function, overwriting it with a string. I can't think of any good reason to write controller code like that.
@IgorMinar suggested a different syntax so that the difference in semantics is obvious. Something like:
I like that this makes the semantics obvious. I don't like that this still violates the "uniform access principle."
Closes #768