Skip to content

bug: ion-button with type="submit" does not submit form in some situations #30968

@ReneZeidler

Description

@ReneZeidler

Prerequisites

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

  1. Open the reproduction URL
  2. Click the submit button (nothing happens)
  3. Clear the text of the input field (the button becomes disabled)
  4. Enter any value into the input field (the button becomes enabled again)
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions