Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] {{on}} modifier on input fired before bound value is updated #19222

Open
olyckne opened this issue Oct 22, 2020 · 9 comments
Open

[Bug] {{on}} modifier on input fired before bound value is updated #19222

olyckne opened this issue Oct 22, 2020 · 9 comments

Comments

@olyckne
Copy link

olyckne commented Oct 22, 2020

🐞 Describe the Bug

When using the {{on}} modifier on an input the callback is fired before the bound value is updated.
From the documentation
<Input @id="input-name" @value={{this.name}} {{on "input" this.validateName}} />

In validateName I would assume I can validate the name by using this.name but it doesn't have the correct value at this time.
This differ from the "old" way of using an argument for the event:
<Input @id="input-name" @value={{this.name}} @input={{this.validateName}} />

This might be indented but it wasn't clear for me, especially coming from using the "old" way.

🔬 Minimal Reproduction

https://ember-twiddle.com/89e1a8168304360b322981218ee218ff

😕 Actual Behavior

When using the {{on}} modifier the bound value isn't updated before the modifier callback is run, which differs from the "old" way using an event argument.
Example:
If I have <Input @value={{this.name}} {{on "input" this.validateName}} /> and I type "John Doe" in this input field,
by the time this.validateName is called this.name will have the value "John Do".
Using the "old" way <Input @value={{this.name}} @input={{this.validateName}} /> this.name will have the value "John Doe".

🤔 Expected Behavior

When using the bound value in the modifier callback I expect it to be the updated value. If this is intended maybe it should at least be clarified in the documentation?
Example:
If I have <Input @value={{this.name}} {{on "input" this.validateName}} /> and I type "John Doe" in this input field.
by the time this.validateName is called I expect this.name to have the value "John Doe".

🌍 Environment

  • Ember: 3.22
  • Node.js/npm: node v12.19.0, npm 6.14.8
  • OS: MacOS 10.15.7 (19H2)
  • Browser: Safari Version 14.0 (15610.1.28.1.9, 15610), Chrome 86.0.4240.111, Firefox 82.0
@buschtoens
Copy link
Contributor

I investigated a related issue in emberjs/ember-test-helpers#1128 (comment). The problem is that {{on}} does not schedule the event listener onto the run loop, specifically the actions queue, unlike @input, which is a classic component action.

When you wrap your listener in schedule('actions', () => ...), it works as expected. I've updated your Twiddle to show that.

@olyckne
Copy link
Author

olyckne commented Feb 24, 2022

When you wrap your listener in schedule('actions', () => ...), it works as expected. I've updated your Twiddle to show that.

@buschtoens hm, the bug is still present for me in your updated Twiddle.

using next(() => ...) seems to fix it though.

@buschtoens
Copy link
Contributor

Interesting! I'm using Firefox and there it works. You're using Chrome, I guess? There it's indeed not working.

next(() => ...) guarantees that the callback is only executed in the next cycle of the event loop, at which point all event listeners and queues of the previous run loop frame are definitely guaranteed to have all been called.

This comes at a cost though: it's essentially calling setTimeout(() => ...), meaning that the call will not resolve synchronously. Consequentially you won't be able to synchronously wait for the call to have occurred nor get its return value in the invoking context.

I wanted to file a very closely related {{on}} modifier bug later anyway — In fact it might even be the same bug. I'll keep an eye out for the Chrome/Firefox discrepancy.

@olyckne
Copy link
Author

olyckne commented Feb 28, 2022

@buschtoens Yeah, I tried in Safari and Chrome.

@tehmaestro
Copy link

I've stumbled across this bug, while refactoring from the {{input helper to the Octane <Input

@rgaiacs
Copy link

rgaiacs commented Sep 22, 2023

Any update on this bug?

@NullVoxPopuli
Copy link
Contributor

NullVoxPopuli commented Sep 22, 2023

The bug relies on the super old two-way binding behavior, and I think we're wanting to encourage people to not use <Input>, and instead use native <input>

In this example, I don't think I was able to reproduce the problem.

@rgaiacs
Copy link

rgaiacs commented Sep 22, 2023

Dear @NullVoxPopuli, Thanks for the fast reply.

Is a PR to https://guides.emberjs.com/release/components/built-in-components/ welcome to high-light this?

@NullVoxPopuli
Copy link
Contributor

absolutely! that'd be wonderful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants