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

Buttons don't respect preventDefault in forms and try to force submit #5032

Closed
Pupix opened this issue Sep 29, 2023 · 3 comments · Fixed by #5268 or #5094 · May be fixed by X-oss-byte/pigweed#61, X-oss-byte/pigweed#70 or X-oss-byte/pigweed#73
Closed
Assignees

Comments

@Pupix
Copy link
Contributor

Pupix commented Sep 29, 2023

What is affected?

Component

Description

Whenever I click on an MWC button inside a form, the validity checks start going off. Usually this happens because buttons inside a form trigger the submit behavior, which can be stopped by calling preventDefault on the event.

Attaching a click listener to a MWC button to prevent the submission doesn't do anything. On a native <button> however the validity check and submission is stopped

Reproduction

You can see an example here, with an icon button, a filled one and a native button. Just start clicking the buttons without filling any of the inputs to notice the jarring effect.

https://lit.dev/playground/#gist=2245bd0b6209c8d3519ff1505c15bd86

The native one works as expected, respecting the preventDefault, the mwc ones keep on trying to submit the form.

Workaround

No workaround.

Setting type="button" would stop the form submission completely instead of preventing the default behavior as expected.

Is this a regression?

No or unsure. This never worked, or I haven't tried before.

Affected versions

1.0.0

Browser/OS/Node environment

Browser: Chrome 117.0.5938.92
OS: Windows 11 Pro 22H2 22621.2283
Node: v18.16.0
npm: 9.6.7

@sorvell
Copy link
Collaborator

sorvell commented Sep 29, 2023

Issue
The issue is that the md-*-button's formSubmitter helper isn't waiting long enough to detect if the event has been prevented. It's waiting a microtask but the microtask queue is flushed every time the browser's event loop advances (i.e. every time a different handler executes). Instead the helper needs to wait a task await new Promise(requestAnimationFrame).

Workaround
As a workaround until this is fixed, you can capture the click event and call preventDefault(). This works because the event is prevented before the formSubmitter starts waiting.

If using TypeScript, you can capture the event easily with the eventOptions decorator @eventOptions({capture: true}). Otherwise, you should add the event imperatively with {capture: true}.

https://lit.dev/playground/#gist=77bf6a3dcca4b1ae302d380db9aacfb9

@sorvell
Copy link
Collaborator

sorvell commented Sep 29, 2023

It looks like this issue may come up elsewhere and needs a holistic fix. All the await 0 are not long enough.

See this example showing microtasks interacting with bubbling listeners.

@asyncLiz
Copy link
Collaborator

Yes! We have an overall tracking bug for ensuring preventDefault() does what is expected. It's on our public roadmap too :)

If you find additional spots where preventDefault() doesn't work as expected, we'd appreciate issues filed!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment