diff --git a/packages/beeq/src/components/input/_storybook/bq-input.stories.tsx b/packages/beeq/src/components/input/_storybook/bq-input.stories.tsx index 1228494e1..63001110c 100644 --- a/packages/beeq/src/components/input/_storybook/bq-input.stories.tsx +++ b/packages/beeq/src/components/input/_storybook/bq-input.stories.tsx @@ -262,3 +262,89 @@ export const NoHelperText: Story = { suffix: true, }, }; + +export const WithForm: Story = { + render: () => { + const handleFormSubmit = (ev: Event) => { + ev.preventDefault(); + const form = ev.target as HTMLFormElement; + const formData = new FormData(form); + const formValues = Object.fromEntries(formData.entries()); + + const codeElement = document.getElementById('form-data'); + if (!codeElement) return; + + codeElement.textContent = JSON.stringify(formValues, null, 2); + }; + + return html` + + +
+ +

Shipping Information

+
+
+ + + + + + +
+ + + + + + +
+ + + + + + Australia + Canada + Mexico + Portugal + Romania + United States + +
+
+ Cancel + Save +
+
+
+ +

Form Data

+
+ // Handle form submit
+ const form = ev.target as HTMLFormElement;
+ const formData = new FormData(form);
+ const formValues = Object.fromEntries(formData.entries()); +
+
+            
+              { // submit the form to see the data here }
+            
+          
+
+
+ + + `; + }, +}; diff --git a/packages/beeq/src/components/input/bq-input.tsx b/packages/beeq/src/components/input/bq-input.tsx index dd4fd7d1b..89574ea56 100644 --- a/packages/beeq/src/components/input/bq-input.tsx +++ b/packages/beeq/src/components/input/bq-input.tsx @@ -1,7 +1,7 @@ -import { Component, Element, Event, EventEmitter, h, Prop, State, Watch } from '@stencil/core'; +import { AttachInternals, Component, Element, Event, EventEmitter, h, Prop, State, Watch } from '@stencil/core'; import { TInputType, TInputValidation, TInputValue } from './bq-input.types'; -import { debounce, hasSlotContent, isDefined, isHTMLElement, TDebounce } from '../../shared/utils'; +import { debounce, hasSlotContent, isDefined, isHTMLElement, isNil, TDebounce } from '../../shared/utils'; /** * @part base - The component's base wrapper. @@ -17,6 +17,7 @@ import { debounce, hasSlotContent, isDefined, isHTMLElement, TDebounce } from '. @Component({ tag: 'bq-input', styleUrl: './scss/bq-input.scss', + formAssociated: true, shadow: { delegatesFocus: true, }, @@ -38,6 +39,7 @@ export class BqInput { // =================================== @Element() el!: HTMLBqInputElement; + @AttachInternals() internals!: ElementInternals; // State() variables // Inlined decorator, alphabetical order @@ -174,10 +176,12 @@ export class BqInput { handleValueChange() { if (Array.isArray(this.value)) { this.hasValue = this.value.some((val) => val.length > 0); + this.internals.setFormValue(this.value.join(',')); return; } this.hasValue = isDefined(this.value); + this.internals.setFormValue(`${this.value}`); } // Events section @@ -209,10 +213,16 @@ export class BqInput { // Ordered by their natural call order // ===================================== - componentDidLoad() { + componentWillLoad() { this.handleValueChange(); } + formResetCallback() { + if (isNil(this.value)) return; + + this.handleClear(); + } + // Listeners // ============== @@ -247,6 +257,7 @@ export class BqInput { if (!isHTMLElement(ev.target, 'input')) return; this.value = this.type === 'number' ? Number(ev.target.value) : ev.target.value; + this.internals.setFormValue(`${this.value}`); this.debounceBqInput = debounce(() => { this.bqInput.emit({ value: this.value, el: this.el }); @@ -259,22 +270,35 @@ export class BqInput { if (!isHTMLElement(ev.target, 'input')) return; this.value = this.type === 'number' ? Number(ev.target.value) : ev.target.value; + this.internals.setFormValue(`${this.value}`); this.bqChange.emit({ value: this.value, el: this.el }); }; - private handleClearClick = (ev: CustomEvent) => { + private handleClear = () => { if (this.disabled) return; - this.inputElem.value = ''; - this.value = this.inputElem.value; + const { inputElem, internals } = this; - this.bqClear.emit(this.el); - this.bqInput.emit({ value: this.value, el: this.el }); - this.bqChange.emit({ value: this.value, el: this.el }); - this.inputElem.focus(); + // Clear input element value + inputElem.value = ''; + this.value = inputElem.value; + + // Update associated form control value + internals.setFormValue(undefined); + }; + private handleClearClick = (ev: CustomEvent) => { ev.stopPropagation(); + this.handleClear(); + + const { bqClear, bqChange, bqInput, el, inputElem } = this; + // Emit events + bqClear.emit(el); + bqInput.emit({ value: this.value, el }); + bqChange.emit({ value: this.value, el }); + // Refocus input element + inputElem.focus(); }; private handleLabelSlotChange = () => {