From 3d395653fcd7113d0e22b4efc5bf7f101ec8d68f Mon Sep 17 00:00:00 2001 From: Konnor Rogers Date: Tue, 16 Dec 2025 10:59:40 -0500 Subject: [PATCH] Bug fix: el.form = 'foo' no longer sets the el.form property (#1815) * Bug fix: el.form = 'foo' no longer sets the el.form property * add changelog entry * add changelog entry * prettier * fix form * skip style attr for button * prettier --- .../docs/docs/resources/changelog.md | 4 ++- .../src/components/button/button.ts | 28 ++++++++++--------- .../src/components/checkbox/checkbox.ts | 7 ----- .../components/color-picker/color-picker.ts | 7 ----- .../webawesome/src/components/input/input.ts | 7 ----- .../webawesome/src/components/radio/radio.ts | 5 ---- .../src/components/select/select.ts | 7 ----- .../src/components/slider/slider.ts | 6 ---- .../src/components/switch/switch.ts | 7 ----- .../src/components/textarea/textarea.ts | 7 ----- .../webawesome-form-associated-element.ts | 20 ++++++++++++- 11 files changed, 37 insertions(+), 68 deletions(-) diff --git a/packages/webawesome/docs/docs/resources/changelog.md b/packages/webawesome/docs/docs/resources/changelog.md index 8b5763c0b..0e2eb6ef7 100644 --- a/packages/webawesome/docs/docs/resources/changelog.md +++ b/packages/webawesome/docs/docs/resources/changelog.md @@ -27,6 +27,8 @@ Components with the Experimental badge sh - Fixed a bug in `` that prevented clicks on the tag's remove button from removing options in multiple mode - Fixed a bug in `` that caused tags to appear in alphabetical order instead of selection order when using `multiple` - Improved performance of `` so initial rendering occurs faster, especially with multiple icons on the page [issue:1729] +- Fixed a bug in Web Awesome form controls that caused `` to set the form property to equal `"foo"` instead of returning an `HTMLFormElement` breaking platform expectations. [pr:1815] +- Fixed a bug in `` causing it to not copy over attributes for form submissions. [pr:1815] - Improved performance of all components by fixing how CSS is imported and reused [issue:1812] - Modified the default `transition` styles of `` to use design tokens [pr:1693] @@ -512,4 +514,4 @@ Many of these changes and improvements were the direct result of feedback from u -Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions) +Did we miss something? [Let us know!](https://github.com/shoelace-style/webawesome/discussions) \ No newline at end of file diff --git a/packages/webawesome/src/components/button/button.ts b/packages/webawesome/src/components/button/button.ts index 19a3dc6cf..146fdb83d 100644 --- a/packages/webawesome/src/components/button/button.ts +++ b/packages/webawesome/src/components/button/button.ts @@ -115,7 +115,6 @@ export default class WaButton extends WebAwesomeFormAssociatedElement { * The "form owner" to associate the button with. If omitted, the closest containing form will be used instead. The * value of this attribute must be an id of a form in the same document or shadow root as the button. */ - @property({ reflect: true }) form: string | null = null; /** Used to override the form owner's `action` attribute. */ @property({ attribute: 'formaction' }) formAction: string; @@ -135,24 +134,27 @@ export default class WaButton extends WebAwesomeFormAssociatedElement { private constructLightDOMButton() { const button = document.createElement('button'); + + for (const attribute of this.attributes) { + if (attribute.name === 'style') { + // Skip style attributes as they *shouldn't* be necessary + continue; + } + button.setAttribute(attribute.name, attribute.value); + } + button.type = this.type; - button.style.position = 'absolute'; - button.style.width = '0'; - button.style.height = '0'; - button.style.clipPath = 'inset(50%)'; - button.style.overflow = 'hidden'; - button.style.whiteSpace = 'nowrap'; + button.style.position = 'absolute !important'; + button.style.width = '0 !important'; + button.style.height = '0 !important'; + button.style.clipPath = 'inset(50%) !important'; + button.style.overflow = 'hidden !important'; + button.style.whiteSpace = 'nowrap !important'; if (this.name) { button.name = this.name; } button.value = this.value || ''; - ['form', 'formaction', 'formenctype', 'formmethod', 'formnovalidate', 'formtarget'].forEach(attr => { - if (this.hasAttribute(attr)) { - button.setAttribute(attr, this.getAttribute(attr)!); - } - }); - return button; } diff --git a/packages/webawesome/src/components/checkbox/checkbox.ts b/packages/webawesome/src/components/checkbox/checkbox.ts index 444472b1d..9af6d20f1 100644 --- a/packages/webawesome/src/components/checkbox/checkbox.ts +++ b/packages/webawesome/src/components/checkbox/checkbox.ts @@ -108,13 +108,6 @@ export default class WaCheckbox extends WebAwesomeFormAssociatedElement { @property({ type: Boolean, reflect: true, attribute: 'checked' }) defaultChecked: boolean = this.hasAttribute('checked'); - /** - * By default, form controls are associated with the nearest containing `
` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** Makes the checkbox a required field. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/components/color-picker/color-picker.ts b/packages/webawesome/src/components/color-picker/color-picker.ts index c039f5034..ce897d69e 100644 --- a/packages/webawesome/src/components/color-picker/color-picker.ts +++ b/packages/webawesome/src/components/color-picker/color-picker.ts @@ -220,13 +220,6 @@ export default class WaColorPicker extends WebAwesomeFormAssociatedElement { */ @property() swatches: string | string[] = ''; - /** - * By default, form controls are associated with the nearest containing `` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** Makes the color picker a required field. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/components/input/input.ts b/packages/webawesome/src/components/input/input.ts index 3dfa32771..930b85ee7 100644 --- a/packages/webawesome/src/components/input/input.ts +++ b/packages/webawesome/src/components/input/input.ts @@ -140,13 +140,6 @@ export default class WaInput extends WebAwesomeFormAssociatedElement { /** Hides the browser's built-in increment/decrement spin buttons for number inputs. */ @property({ attribute: 'without-spin-buttons', type: Boolean }) withoutSpinButtons = false; - /** - * By default, form controls are associated with the nearest containing `` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** Makes the input a required field. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/components/radio/radio.ts b/packages/webawesome/src/components/radio/radio.ts index d2b5377f4..0f7d6f991 100644 --- a/packages/webawesome/src/components/radio/radio.ts +++ b/packages/webawesome/src/components/radio/radio.ts @@ -39,11 +39,6 @@ export default class WaRadio extends WebAwesomeFormAssociatedElement { /** @internal Used by radio group to force disable radios while preserving their original disabled state. */ @state() forceDisabled = false; - /** - * The string pointing to a form's id. - */ - @property({ reflect: true }) form: string | null = null; - /** The radio's value. When selected, the radio group will receive this value. */ @property({ reflect: true }) value: string; diff --git a/packages/webawesome/src/components/select/select.ts b/packages/webawesome/src/components/select/select.ts index ddc51ce33..46d1b8cf6 100644 --- a/packages/webawesome/src/components/select/select.ts +++ b/packages/webawesome/src/components/select/select.ts @@ -257,13 +257,6 @@ export default class WaSelect extends WebAwesomeFormAssociatedElement { */ @property({ attribute: 'with-hint', type: Boolean }) withHint = false; - /** - * By default, form controls are associated with the nearest containing `` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** The select's required attribute. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/components/slider/slider.ts b/packages/webawesome/src/components/slider/slider.ts index 55e7df338..e896e6174 100644 --- a/packages/webawesome/src/components/slider/slider.ts +++ b/packages/webawesome/src/components/slider/slider.ts @@ -167,12 +167,6 @@ export default class WaSlider extends WebAwesomeFormAssociatedElement { /** The starting value from which to draw the slider's fill, which is based on its current value. */ @property({ attribute: 'indicator-offset', type: Number }) indicatorOffset: number; - /** - * The form to associate this control with. If omitted, the closest containing `` will be used. The value of - * this attribute must be an ID of a form in the same document or shadow root. - */ - @property({ reflect: true }) form = null; - /** The minimum value allowed. */ @property({ type: Number }) min: number = 0; diff --git a/packages/webawesome/src/components/switch/switch.ts b/packages/webawesome/src/components/switch/switch.ts index 14f06084e..99e3b8de0 100644 --- a/packages/webawesome/src/components/switch/switch.ts +++ b/packages/webawesome/src/components/switch/switch.ts @@ -80,13 +80,6 @@ export default class WaSwitch extends WebAwesomeFormAssociatedElement { @property({ type: Boolean, attribute: 'checked', reflect: true }) defaultChecked: boolean = this.hasAttribute('checked'); - /** - * By default, form controls are associated with the nearest containing `` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** Makes the switch a required field. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/components/textarea/textarea.ts b/packages/webawesome/src/components/textarea/textarea.ts index 5f63a5e50..3e7870f7d 100644 --- a/packages/webawesome/src/components/textarea/textarea.ts +++ b/packages/webawesome/src/components/textarea/textarea.ts @@ -107,13 +107,6 @@ export default class WaTextarea extends WebAwesomeFormAssociatedElement { /** Makes the textarea readonly. */ @property({ type: Boolean, reflect: true }) readonly = false; - /** - * By default, form controls are associated with the nearest containing `` element. This attribute allows you - * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in - * the same document or shadow root for this to work. - */ - @property({ reflect: true }) form = null; - /** Makes the textarea a required field. */ @property({ type: Boolean, reflect: true }) required = false; diff --git a/packages/webawesome/src/internal/webawesome-form-associated-element.ts b/packages/webawesome/src/internal/webawesome-form-associated-element.ts index f84116325..440f13aee 100644 --- a/packages/webawesome/src/internal/webawesome-form-associated-element.ts +++ b/packages/webawesome/src/internal/webawesome-form-associated-element.ts @@ -23,7 +23,8 @@ export interface WebAwesomeFormControl extends WebAwesomeElement { checked?: boolean; defaultSelected?: boolean; selected?: boolean; - form?: string | null; + get form(): HTMLFormElement | null; + set form(val: string); value?: unknown; @@ -203,6 +204,23 @@ export class WebAwesomeFormAssociatedElement return this.internals.form; } + /** + * By default, form controls are associated with the nearest containing `` element. This attribute allows you + * to place the form control outside of a form and associate it with the form that has this `id`. The form must be in + * the same document or shadow root for this to work. + */ + set form(val: string) { + if (val) { + this.setAttribute('form', val); + } else { + this.removeAttribute('form'); + } + } + + get form(): HTMLFormElement | null { + return this.internals.form; + } + @property({ attribute: false, state: true, type: Object }) get validity() { return this.internals.validity;