diff --git a/packages/ui-library/src/components/checkbox/index.ts b/packages/ui-library/src/components/checkbox/index.ts index 29ce0abea..c43afffd8 100644 --- a/packages/ui-library/src/components/checkbox/index.ts +++ b/packages/ui-library/src/components/checkbox/index.ts @@ -42,7 +42,7 @@ export class BlrCheckbox extends LitElement { @property() label!: string; @property() checkInputId?: string = ''; @property() arialabel?: string; - + @property() required?: boolean; @property() disabled?: boolean; @property() checked?: boolean; @property() indeterminate?: boolean; @@ -65,6 +65,22 @@ export class BlrCheckbox extends LitElement { @state() protected currentCheckedState: boolean | undefined = this.checked; @state() protected currentIndeterminateState: boolean | undefined = this.indeterminate; + // TESTING BEGIN + // Identify the element as a form-associated custom element + static formAssociated = true; + private _internals: ElementInternals; + + constructor() { + super(); + // Get access to the internal form control APIs + this._internals = this.attachInternals(); + } + + public checkValidity() { + return this._internals.checkValidity; + } + // TESTING END + protected updated(changedProperties: Map) { if (changedProperties.has('checked')) { this.currentCheckedState = this.checked || false; @@ -78,21 +94,6 @@ export class BlrCheckbox extends LitElement { } } - connectedCallback() { - super.connectedCallback(); - addEventListener('propChanged', this._onPropChanged); - } - - disconnectedCallback() { - super.disconnectedCallback(); - removeEventListener('propChanged', this._onPropChanged); - } - - _onPropChanged = (event: any) => { - this.hasError = event.detail.hasError; - this.errorMessage = event.detail.errorMessage; - }; - protected handleChange(event: Event) { if (!this.disabled && !this.readonly) { this.currentIndeterminateState = false; @@ -277,10 +278,11 @@ export class BlrCheckbox extends LitElement { id=${this.checkInputId || nothing} name=${this.name || nothing} ?disabled=${this.disabled} - ?checked=${this.currentCheckedState} + ?checked=${this.checked} ?indeterminate=${this.currentIndeterminateState} ?readonly=${this.readonly} ?hasError=${this.hasError} + ?required="${this.required}" @change=${this.handleChange} aria-hidden="true" /> diff --git a/packages/ui-library/src/components/form-example-without-slot/index.ts b/packages/ui-library/src/components/form-example-without-slot/index.ts index f70d69c94..8593a3466 100644 --- a/packages/ui-library/src/components/form-example-without-slot/index.ts +++ b/packages/ui-library/src/components/form-example-without-slot/index.ts @@ -6,15 +6,22 @@ import { property, query } from 'lit/decorators.js'; export class BlrFormExampleWithoutSlot extends LitElement { @property() theme: ThemeType = 'Light'; @property() firstInputValue: string = ''; + @property() firstTextInputHasError: boolean = false; + @property() secondTextInputHasError: boolean = false; + @property() radioHasError: boolean = false; @property() secondInputValue: string = ''; - @property() errorMessage: string = ''; - @property() firstNameHasError?: boolean = false; - @property() lastNameHasError?: boolean = false; - @property({ reflect: true }) checkBoxChecked: boolean = false; + @property() checkInputHasError?: boolean = false; + @property() selectHasError?: boolean = false; + @property() checkBoxChecked: boolean = false; + @property() textInputErrorMessage: string = 'input field required'; + @property() selectErrorMessage: string = 'at least one selection required'; + @property() radioErrorMessage: string = 'at least one selection required'; @query('blr-text-input[name="firstInput"]') firstInputElement!: HTMLElement; @query('blr-text-input[name="secondInput"]') secondInputElement!: HTMLElement; @query('blr-checkbox[name="checkInput"]') checkboxInputElement!: HTMLElement; + @query('blr-select[name="select"]') selectElement!: HTMLElement; + @query('blr-radio[name="radio"]') radioElement!: HTMLElement; protected render() { return html` @@ -36,6 +43,8 @@ export class BlrFormExampleWithoutSlot extends LitElement { showinputicon="true" @blrTextValueChange="${this.handleFirstInputChange}" required="true" + .hasError=${this.firstTextInputHasError} + errorMessage=${this.textInputErrorMessage} > + + + + + + { - this.dispatchEvent( - new CustomEvent('propChanged', { - detail: { hasError: false, errorMessage: '' }, - bubbles: true, - composed: true, - }) - ); - }, 3000); - return; + if (!shadowFirstInputElement?.checkValidity()) { + this.firstTextInputHasError = true; } + if (!shadowSecondInputElement?.checkValidity()) { + this.secondTextInputHasError = true; + } + + if (!shadowCheckInputElement?.checkValidity()) { + this.checkInputHasError = true; + } + + if (!shadowSelectElement?.checkValidity()) { + this.selectHasError = true; + } + + if (!shadowRadioElement?.checkValidity()) { + this.radioHasError = true; + } + + // just to simulate the value change. Remove later + setTimeout(() => { + this.firstTextInputHasError = false; + this.secondTextInputHasError = false; + this.checkInputHasError = false; + this.selectHasError = false; + this.radioHasError = false; + }, 2000); + console.log( `First Input: ${this.firstInputValue}, Second Input: ${this.secondInputValue}, checkbox checked: ${this.checkBoxChecked}` ); diff --git a/packages/ui-library/src/components/radio/index.ts b/packages/ui-library/src/components/radio/index.ts index da788a7cf..856eff1f2 100644 --- a/packages/ui-library/src/components/radio/index.ts +++ b/packages/ui-library/src/components/radio/index.ts @@ -35,6 +35,22 @@ export class BlrRadio extends LitElement { @property() theme: ThemeType = 'Light'; + // TESTING BEGIN + // Identify the element as a form-associated custom element + static formAssociated = true; + private _internals: ElementInternals; + + constructor() { + super(); + // Get access to the internal form control APIs + this._internals = this.attachInternals(); + } + + public checkValidity() { + return this._internals.checkValidity; + } + // TESTING END + protected render() { if (this.size) { const dynamicStyles = this.theme === 'Light' ? [formLight, radioLight] : [formDark, radioDark]; diff --git a/packages/ui-library/src/components/select/index.ts b/packages/ui-library/src/components/select/index.ts index ec0a59dad..5e3c71955 100644 --- a/packages/ui-library/src/components/select/index.ts +++ b/packages/ui-library/src/components/select/index.ts @@ -51,6 +51,22 @@ export class BlrSelect extends LitElement { @state() protected isFocused = false; + // TESTING BEGIN + // Identify the element as a form-associated custom element + static formAssociated = true; + private _internals: ElementInternals; + + constructor() { + super(); + // Get access to the internal form control APIs + this._internals = this.attachInternals(); + } + + public checkValidity() { + return this._internals.checkValidity; + } + // TESTING END + protected _optionElements: Element[] | undefined; protected handleFocus = () => { diff --git a/packages/ui-library/src/components/text-input/index.ts b/packages/ui-library/src/components/text-input/index.ts index 59be8192a..f6dbf71b4 100644 --- a/packages/ui-library/src/components/text-input/index.ts +++ b/packages/ui-library/src/components/text-input/index.ts @@ -69,20 +69,21 @@ export class BlrTextInput extends LitElement { @state() protected currentType: InputTypes = this.type; @state() protected isFocused = false; - connectedCallback() { - super.connectedCallback(); - addEventListener('propChanged', this._onPropChanged); - } + // TESTING BEGIN + // Identify the element as a form-associated custom element + static formAssociated = true; + private _internals: ElementInternals; - disconnectedCallback() { - super.disconnectedCallback(); - removeEventListener('propChanged', this._onPropChanged); + constructor() { + super(); + // Get access to the internal form control APIs + this._internals = this.attachInternals(); } - _onPropChanged = (event: any) => { - this.hasError = event.detail.hasError; - this.errorMessage = event.detail.errorMessage; - }; + public checkValidity() { + return this._internals.checkValidity; + } + // TESTING END protected togglePassword = () => { this.currentType = this.currentType === 'password' ? 'text' : 'password'; @@ -211,7 +212,7 @@ export class BlrTextInput extends LitElement { @blur=${this.handleBlur} @focus=${this.handleFocus} maxlength="${this.maxLength}" - pattern="${this.pattern}" + pattern="${this.pattern || nothing}" @select=${this.handleSelect} />