-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Description
Prerequisites
- I have read the Contributing Guidelines.
- I agree to follow the Code of Conduct.
- I have searched for existing issues that already report this problem, without success.
Ionic Framework Version
v8.x
Current Behavior
<ion-button> with type="submit" does not cause the associated <form> to be submitted even though it is not disabled
Expected Behavior
<ion-button> with type="submit" should always submit the associated <form> when it is clicked and not disabled
Steps to Reproduce
- Open the reproduction URL
- Click the submit button (nothing happens)
- Clear the text of the input field (the button becomes disabled)
- Enter any value into the input field (the button becomes enabled again)
- Click the button again (the text "Form submitted!" appears on the page)
Code Reproduction URL
https://stackblitz.com/edit/ion-button-submit-bug
Ionic Info
Ionic:
Ionic CLI : 7.2.1
Ionic Framework : @ionic/angular 8.7.17
@angular-devkit/build-angular : 21.1.4
@angular-devkit/schematics : 21.1.4
@angular/cli : 21.1.4
@ionic/angular-toolkit : 12.3.0
Utility:
cordova-res : not installed globally
native-run : not installed globally
System:
NodeJS : v20.19.1 (/usr/local/bin/node)
npm : 10.8.2
OS : Linux 5.0
Additional Information
This issue is a regression, caused by the Stencil update to 4.29.3 in Ionic 8.6.0 (Copy of the reproduction with Ionic 8.5.9: https://stackblitz.com/edit/ion-button-submit-before-regression). This Stencil update changed some things in component initialization order (that I don't fully understand). Other issues that were caused by the same update which have already been resolved: #30613, #30552
The root cause is the "hidden button" in ion-button, which is used to submit the form. The disabled state of the hidden button is supposed to be kept in sync with the disabled state of the ion-button, but this doesn't work at initialization.
The button gets created on first render with the current disabled state of the ion-button here:
| newFormButtonEl.disabled = this.disabled; |
In the reproduction, the button is initially disabled, so the hidden button is also disabled.
After that, it's supposed to be updated using the @Watch decorator:
https://github.com/ionic-team/ionic-framework/blob/main/core/src/components/button/button.tsx#L62-L68
Some time after the first render the disabled state changes without triggering the @Watch listener (probably because the ion-button isn't fully initialized yet?).
In my reproduction I caused this update using async form validation, because that's how I encountered this issue in production, but I'm sure there's other situations that could trigger the same behavior.