This repository was archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 27.4k
feat(ngModelOptions): allow to debounce 'default' only, and add catch… #16335
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
So, afaict all events that are not included in
updateOn
will get thedefault
timeout.Is this intended? It seems very counter-intuitive (and there don't seem to be tests and docs for that.)
(Sorry for joining the party late 😞)
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 guess this was partly to be in keeping with the previous behaviour, which meant that all items that were not listed the
debounce
property got the default value. Now only the items that are not listed in both theupdateOn
and thedebounce
property get the default value.But given that we are going with the exciting new catch-all
*
then we should use that for things that are not specified in either place.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 based this on the assumption that all events that are not in updateOn are the control's default events, i.e. the event handlers that the control defines itself which are never explicitly exposed via the API. For example, our inputs usually have the input (change for IE) as the default event, but this is not exposed on the ngModel controller, so I cannot match against it directly.
That also means if you add 'input' in 'onUpdate' it is not considered a 'default' event anymore, and doesn't receive debounce that you define in 'default'
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.
Theoretically,
trigger
can be any event, because it is a public documented API of $setViewValue. The way this is implemented now is a bit weird (and probably broken). Basically,$setViewValue
seems to assume that IFtrigger
is provided as an argument (it is optional), then it is on of the "default" event:This holds true inside the framework (i.e. we only pass the
trigger
argument when calling$setViewValue
from the input's "default" event. But there is nothing stopping people from passing their events.I believe the current situation is unintuitive (and underdocumented). I consider it a bug: #14886.
Off the top of my head, the whole mechanism should be refactored in a way that allows:
default
debouncing to default event(s).*
) debouncing whentrigger
is not specified or not specifically mentioned inngModelOptions#debounce
(and not the default event).WDYT?
(Note: It would be a breaking change, so if we agree on it should land it ASAP.)
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.
There's a difference between the default events / triggers und the updateOn events / triggers. Only the default triggers call setViewValue - the updateOn triggers call debounceViewValue directly (i.e. they require that the control calls setViewValue in the correct circumstances with the default event). So we assume that updateOn adds additional events to the default event, and that setViewValue is always called with the control's default event. Of course this is at the moment quite sketchy because we assume that the default event is input and that updateOn is blur, mouseup etc. (This whole distinction is something I haven't really thought about when writing this PR. I assumed the updateOn events called setViewValue).
That is true, but imo this is not an intended use case. Every control defines its own setViewValue triggers (default triggers) - most are DOM events, but they don't have to. Calling a control's ngModelController.$setViewValue with a different trigger, i.e. programatically, is supported, but why would you do that? I can't think of a scenario where it would be necessary. If you need to update the model programatically, you do it from the scope. $setViewValue should only be called with the triggers the controls uses itself.
We can do this for our own inputs, but how would we handle custom controls that do not define their default events? I don't think many custom controls will be updated to define their default controls.
As explained above, I'd also argue this contradicts "1. Applying the appropriate debouncing for each event, (even for non-default events passed by users)." because if a control has well defined default events, why should you be able to set the viewValue with a different trigger?
If we have well defined default events, then we should also check if there's event duplication in updateOn - for example, in this plnkr, we call $$debounceViewValueCommit twice: http://plnkr.co/edit/0niAourDe8t2yknzzNX7?p=preview
Ok. But * would apply to default events if default isn't applied in debounce, right?
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 probably haven't thought it through. It's just that
default
is confusing. Maybe it is the fact thatdefault
inupdateOn
has a different meaning than indebounce
. And I also don't understand the reasoning behind this 😕:TBH, I don't have a good suggestion of how this API should be (without breaking it completely 😁).
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.
Does 'default' really have a different meaning in updateOn and debounce? I don't think so, maybe you can elaborate.
What is the default event? The current docs say it's an event "that matches the default events belonging to the control." And imo this can only be the events that, when fired, call $setViewValue, because this is the glue between the control and ngModel. Then, if updateOnDefault is not set, setViewValue does not have to call debounceViewValue, because it should not update the modelValue.
Basically, that means you should only call setViewValue if you actually update the $viewValue. Imo, it doesn't make sense to have something like setViewValue(value, 'blur'), because in what circumstance can the blur event actually update the value?
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.
AFAICT (by looking at the code - especially before thi PR),
updteOn: default
seemed to (mostly) refer to the default event for the component, while ``debounce.default` seemed to refer to a default debounce; i.e. a value to be used for an event type for which no value is explicitly set.My assumption was that we would change that so that
debounce.*
would now mean the "default"/"fallback" debounce (for any event for which no explicit debounce is set) anddebounce.default
would refer to the debounce for the default event.That is unexpected (to me). I would expect it to call
debounceViewValueCommit
for any event that is included inupdateOn
(in addition to the default event).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.
Ok, I see. I think that now the behavior is more consistent, as "default" refers to the same thing in updateOn and default.
The setViewValue behavior is technically independant from this change - we could change it at a later point, but personally I think it's fine as it is.