Skip to content

Commit 0c76135

Browse files
fix(button): sync disabled state and type in renderHiddenButton (#31225)
Issue number: resolves #30968 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> `<ion-button>` with type="submit" does not cause the associated `<form>` to be submitted even though it is not disabled. When the text of the input field is cleared and then input re-added, you can submit the input. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> The visible and hidden button should always have the same disabled state. `<ion-button>` with type="submit" should always submit the associated `<form>` when it is enabled. - Add `formButtonEl.disabled = this.disabled;` and `formButtonEl.type = this.type;` to button.tsx in `renderHiddenButton()`. This addition syncs the disabled status and type of the button when that happens. - Add a test in to to `packages/angular/test/base/e2e/src/lazy/form.spec.ts` which should ensure any changes in button type are synced. The test gets the hidden button type, changes the visible button state, and then expects the hidden button state to change as well. - Per conversations around this PR, testing disabled state sync will need a dev build due to the nature of the issue. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change: 1. Describe the impact and migration path for existing applications below. 2. Update the BREAKING.md file with the breaking change. 3. Add "BREAKING CHANGE: [...]" to the commit description when merging. See https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer for more information. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Related to a stencil update that affected when @watch('disabled') fires. --------- Co-authored-by: Shane <shane@shanessite.net>
1 parent a35f8a9 commit 0c76135

2 files changed

Lines changed: 40 additions & 1 deletion

File tree

core/src/components/button/button.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,13 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
195195

196196
/**
197197
* If the form already has a rendered form button
198-
* then do not append a new one again.
198+
* then do not append a new one again. Sync the
199+
* disabled state and type if it changes after button
200+
* creation (e.g., runtime property updates).
199201
*/
200202
if (formButtonEl !== null && formEl.contains(formButtonEl)) {
203+
formButtonEl.disabled = this.disabled;
204+
formButtonEl.type = this.type;
201205
return;
202206
}
203207

core/src/components/button/test/form-reference/button.e2e.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,41 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, config }) =>
153153

154154
expect(submitEvent).toHaveReceivedEvent();
155155
});
156+
157+
test('should keep hidden button type in sync with visible button', async ({ page }) => {
158+
// Set the form to have a submit button
159+
await page.setContent(
160+
`
161+
<form id="myForm"></form>
162+
<ion-button form="myForm" type="submit">
163+
Submit
164+
</ion-button>
165+
`,
166+
config
167+
);
168+
169+
// Get visible button
170+
const button = page.locator('ion-button');
171+
172+
// Get type of the hidden button
173+
const getHiddenType = () =>
174+
page.evaluate(() => {
175+
const hidden = document.querySelector('form button[style*="display: none"]') as HTMLButtonElement;
176+
177+
return hidden?.type;
178+
});
179+
180+
// Type of hidden button should be submit to start
181+
expect(await getHiddenType()).toBe('submit');
182+
183+
// Set type of visible button to reset
184+
await button.evaluate((el: HTMLIonButtonElement) => {
185+
el.type = 'reset';
186+
});
187+
188+
// Expect hidden button type to be reset
189+
await expect.poll(async () => await getHiddenType()).toBe('reset');
190+
});
156191
});
157192

158193
test.describe(title('should throw a warning if the form cannot be found'), () => {

0 commit comments

Comments
 (0)