From 62c58b3a8c318cb64b34a4b429e5c54e1429528a Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Tue, 10 Jan 2023 15:05:07 -0500 Subject: [PATCH] simplify validation logic --- src/components/radio-group/radio-group.ts | 75 +++++++++-------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/src/components/radio-group/radio-group.ts b/src/components/radio-group/radio-group.ts index 2f7c4c3c..0b396767 100644 --- a/src/components/radio-group/radio-group.ts +++ b/src/components/radio-group/radio-group.ts @@ -38,17 +38,16 @@ import type { CSSResultGroup } from 'lit'; export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFormControl { static styles: CSSResultGroup = styles; - protected readonly formControlController = new FormControlController(this, { - defaultValue: control => control.defaultValue - }); + protected readonly formControlController = new FormControlController(this); private readonly hasSlotController = new HasSlotController(this, 'help-text', 'label'); + private customValidityMessage = ''; + private validationTimeout: number; @query('slot:not([name])') defaultSlot: HTMLSlotElement; - @query('.radio-group__validation-input') input: HTMLInputElement; + @query('.radio-group__validation-input') validationInput: HTMLInputElement; @state() private hasButtonGroup = false; @state() private errorMessage = ''; - @state() private customErrorMessage = ''; @state() defaultValue = ''; /** @@ -181,16 +180,10 @@ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFor } } - private showNativeErrorMessage() { - this.input.hidden = false; - this.input.reportValidity(); - setTimeout(() => (this.input.hidden = true), 10000); - } - private updateCheckedRadio() { const radios = this.getAllRadios(); radios.forEach(radio => (radio.checked = radio.value === this.value)); - this.formControlController.setValidity(this.validity.valid); + this.formControlController.setValidity(this.checkValidity()); } @watch('value') @@ -202,53 +195,41 @@ export default class SlRadioGroup extends ShoelaceElement implements ShoelaceFor /** Checks for validity but does not show the browser's validation message. */ checkValidity() { - return this.validity.valid; - } + const isRequiredAndEmpty = this.required && !this.value; + const hasCustomValidityMessage = this.customValidityMessage !== ''; - /** Sets a custom validation message. If `message` is not empty, the field will be considered invalid. */ - setCustomValidity(message = '') { - this.customErrorMessage = message; - this.errorMessage = message; - - if (!message) { - this.formControlController.setValidity(true); - } else { - this.formControlController.setValidity(false); - this.input.setCustomValidity(message); + if (isRequiredAndEmpty || hasCustomValidityMessage) { + return false; } + + return true; } - get validity(): ValidityState { - const hasMissingData = !((this.value && this.required) || !this.required); - const hasCustomError = this.customErrorMessage !== ''; - - return { - badInput: false, - customError: hasCustomError, - patternMismatch: false, - rangeOverflow: false, - rangeUnderflow: false, - stepMismatch: false, - tooLong: false, - tooShort: false, - typeMismatch: false, - valid: hasMissingData || hasCustomError ? false : true, - valueMissing: !hasMissingData - }; + /** Sets a custom validation message. Pass an empty string to restore validity. */ + setCustomValidity(message = '') { + this.customValidityMessage = message; + this.errorMessage = message; + this.validationInput.setCustomValidity(message); + this.formControlController.updateValidity(); } /** Checks for validity and shows the browser's validation message if the control is invalid. */ reportValidity(): boolean { - const validity = this.validity; + const isValid = this.checkValidity(); - this.errorMessage = this.customErrorMessage || validity.valid ? '' : this.input.validationMessage; - this.formControlController.setValidity(validity.valid); + this.errorMessage = this.customValidityMessage || isValid ? '' : this.validationInput.validationMessage; + this.formControlController.setValidity(isValid); + this.validationInput.hidden = true; + clearTimeout(this.validationTimeout); - if (!validity.valid) { - this.showNativeErrorMessage(); + if (!isValid) { + // Show the browser's constraint validation message + this.validationInput.hidden = false; + this.validationInput.reportValidity(); + this.validationTimeout = setTimeout(() => (this.validationInput.hidden = true), 10000) as unknown as number; } - return validity.valid; + return isValid; } render() {