Skip to content

Commit 92e2b07

Browse files
authored
Bug: implement form control validity property (#202)
Bug: implement form control validity property
2 parents 205ceee + 6894546 commit 92e2b07

File tree

4 files changed

+54
-26
lines changed

4 files changed

+54
-26
lines changed

packages/uui-base/lib/mixins/FormControlMixin.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export declare abstract class FormControlMixinInterface extends LitElement {
1616
formResetCallback(): void;
1717
checkValidity(): boolean;
1818
get validationMessage(): string;
19+
get validity(): ValidityState;
1920
public setCustomValidity(error: string): void;
2021
protected _value: FormDataEntryValue | FormData;
2122
protected _internals: any;
@@ -302,6 +303,9 @@ export const FormControlMixin = <T extends Constructor<LitElement>>(
302303

303304
const hasError = Object.values(this._validityState).includes(true);
304305

306+
// https://developer.mozilla.org/en-US/docs/Web/API/ValidityState#valid
307+
this._validityState.valid = !hasError;
308+
305309
if (hasError) {
306310
this.dispatchEvent(
307311
new UUIFormControlEvent(UUIFormControlEvent.INVALID)
@@ -347,6 +351,11 @@ export const FormControlMixin = <T extends Constructor<LitElement>>(
347351
return this._internals?.checkValidity();
348352
}
349353

354+
// https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity
355+
public get validity(): ValidityState {
356+
return this._validityState;
357+
}
358+
350359
get validationMessage() {
351360
return this._internals?.validationMessage;
352361
}

packages/uui-button/lib/uui-button.element.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
UUIHorizontalShakeKeyframes,
44
} from '@umbraco-ui/uui-base/lib/animations';
55
import { demandCustomElement } from '@umbraco-ui/uui-base/lib/utils';
6-
import { LabelMixin } from '@umbraco-ui/uui-base/lib/mixins';
6+
import { FormControlMixin, LabelMixin } from '@umbraco-ui/uui-base/lib/mixins';
77
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
88
import {
99
InterfaceLookDefaultValue,
@@ -14,7 +14,7 @@ import {
1414
iconWrong,
1515
} from '@umbraco-ui/uui-icon-registry-essential/lib/svgs';
1616
import { css, html, LitElement } from 'lit';
17-
import { property } from 'lit/decorators.js';
17+
import { property, query } from 'lit/decorators.js';
1818

1919
export type UUIButtonState = null | 'waiting' | 'success' | 'failed';
2020

@@ -41,7 +41,9 @@ export type UUIButtonType = 'submit' | 'button' | 'reset';
4141
* @cssprop --uui-button-contrast-disabled - overwrite the text color for disabled state
4242
*/
4343
@defineElement('uui-button')
44-
export class UUIButtonElement extends LabelMixin('', LitElement) {
44+
export class UUIButtonElement extends FormControlMixin(
45+
LabelMixin('', LitElement)
46+
) {
4547
static styles = [
4648
UUIHorizontalShakeKeyframes,
4749
css`
@@ -554,20 +556,18 @@ export class UUIButtonElement extends LabelMixin('', LitElement) {
554556
@property({ type: String, reflect: true })
555557
state: UUIButtonState = null;
556558

557-
/**
558-
* This is a static class field indicating that the element is can be used inside a native form and participate in its events. It may require a polyfill, check support here https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/attachInternals. Read more about form controls here https://web.dev/more-capable-form-controls/
559-
* @type {boolean}
560-
*/
561-
static readonly formAssociated = true;
562-
563-
private _internals;
559+
@query('#button')
560+
protected _button!: HTMLInputElement;
564561

565562
constructor() {
566563
super();
567-
this._internals = (this as any).attachInternals();
568564
this.addEventListener('click', this._onHostClick);
569565
}
570566

567+
protected getFormElement(): HTMLElement {
568+
return this._button;
569+
}
570+
571571
private _onHostClick(e: MouseEvent) {
572572
if (this.disabled) {
573573
e.preventDefault();
@@ -637,7 +637,7 @@ export class UUIButtonElement extends LabelMixin('', LitElement) {
637637

638638
render() {
639639
return html`
640-
<button ?disabled=${this.disabled} aria-label="${this.label}">
640+
<button id="button" ?disabled=${this.disabled} aria-label="${this.label}">
641641
${this.renderState()} ${this.renderLabel()}
642642
<slot name="extra"></slot>
643643
</button>

packages/uui-combobox/lib/uui-combobox.element.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ export class UUIComboboxElement extends FormControlMixin(LitElement) {
7676
`,
7777
];
7878

79+
get value() {
80+
return this._value;
81+
}
82+
set value(newValue) {
83+
super.value = newValue;
84+
85+
if (typeof newValue === 'string') {
86+
this._updateValue(newValue);
87+
}
88+
}
89+
7990
/**
8091
* The search input.
8192
* @type { string }
@@ -151,12 +162,18 @@ export class UUIComboboxElement extends FormControlMixin(LitElement) {
151162

152163
if (typeof this.value === 'string') {
153164
await this.updateComplete;
154-
this._comboboxList.value = this.value;
155-
this._displayValue = this._comboboxList?.displayValue || '';
165+
this._updateValue(this.value);
156166
}
157167
}
158168
}
159169

170+
private _updateValue(value: string) {
171+
if (this._comboboxList) {
172+
this._comboboxList.value = value;
173+
this._displayValue = this._comboboxList?.displayValue || '';
174+
}
175+
}
176+
160177
protected getFormElement(): HTMLElement | undefined {
161178
return this._input;
162179
}

packages/uui-form/lib/uui-form.story.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,20 @@ export const Overview: Story = () => {
137137
<uui-form-layout-item>
138138
<uui-label for="MyCombobox" slot="label" required>Combobox</uui-label>
139139
<uui-combobox id="MyCombobox" name="combobox" required>
140-
<uui-combobox-list-option value="1"
141-
>Option 1</uui-combobox-list-option
142-
>
143-
<uui-combobox-list-option value="2"
144-
>Option 2</uui-combobox-list-option
145-
>
146-
<uui-combobox-list-option value="3"
147-
>Option 3</uui-combobox-list-option
148-
>
149-
<uui-combobox-list-option value="4"
150-
>Option 4</uui-combobox-list-option
151-
>
140+
<uui-combobox-list>
141+
<uui-combobox-list-option value="1"
142+
>Option 1</uui-combobox-list-option
143+
>
144+
<uui-combobox-list-option value="2"
145+
>Option 2</uui-combobox-list-option
146+
>
147+
<uui-combobox-list-option value="3"
148+
>Option 3</uui-combobox-list-option
149+
>
150+
<uui-combobox-list-option value="4"
151+
>Option 4</uui-combobox-list-option
152+
>
153+
</uui-combobox-list>
152154
</uui-combobox>
153155
</uui-form-layout-item>
154156

0 commit comments

Comments
 (0)