diff --git a/docs/components/radio-group.md b/docs/components/radio-group.md index 49ad989bc..dd930b7f1 100644 --- a/docs/components/radio-group.md +++ b/docs/components/radio-group.md @@ -86,7 +86,60 @@ const App = () => ( ); ``` -### Custom Validity +### Validation + +Setting the `required` attribute to make selecting a an option mandatory. If a value has not been selected, it will prevent the form from submitting and display an error message. + +```html preview +
+ + Not me + Me neither + Choose me + +
+ Submit +
+ +``` + +```jsx react +import { SlButton, SlIcon, SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react'; +const App = () => { + function handleSubmit(event) { + event.preventDefault(); + alert('All fields are valid!'); + } + return ( +
+ + + Not me + + + Me neither + + + Choose me + + +
+ + Submit + +
+ ); +}; +``` + +#### Custom Validity Use the `setCustomValidity()` method to set a custom validation message. This will prevent the form from submitting and make the browser display the error message you provide. To clear the error, call this function with an empty string. @@ -125,10 +178,10 @@ Use the `setCustomValidity()` method to set a custom validation message. This wi import { useEffect, useRef } from 'react'; import { SlButton, SlIcon, SlRadio, SlRadioGroup } from '@shoelace-style/shoelace/dist/react'; const App = () => { - const radio = useRef(null); + const radioGroup = useRef(null); const errorMessage = 'You must choose this option'; - function handleChange(event) { - radio.current.setCustomValidity(radio.current.checked ? '' : errorMessage); + function handleChange() { + radioGroup.current.setCustomValidity(radioGroup.current.value === '3' ? '' : errorMessage); } function handleSubmit(event) { event.preventDefault(); @@ -139,14 +192,14 @@ const App = () => { }, []); return (
- - + + Not me - + Me neither - + Choose me diff --git a/src/components/radio-group/radio-group.ts b/src/components/radio-group/radio-group.ts index e4ab68182..a2e973f71 100644 --- a/src/components/radio-group/radio-group.ts +++ b/src/components/radio-group/radio-group.ts @@ -35,6 +35,7 @@ export default class SlRadioGroup extends LitElement { @state() private hasButtonGroup = false; @state() private isInvalid = false; @state() private errorMessage = ''; + @state() private customErrorMessage = ''; /** The radio group label. Required for proper accessibility. Alternatively, you can use the label slot. */ @property() label = ''; @@ -64,7 +65,8 @@ export default class SlRadioGroup extends LitElement { this.preventInvalidSubmit(); } - setCustomValidity(message: string) { + setCustomValidity(message = '') { + this.customErrorMessage = message; this.errorMessage = message; if (!message) { @@ -77,11 +79,13 @@ export default class SlRadioGroup extends LitElement { } get validity(): ValidityState { - const isValid = (this.value && this.required) || !this.required; - + const hasMissingData = !((this.value && this.required) || !this.required); + const hasCustomError = this.customErrorMessage !== ''; + console.log(hasMissingData); + return { badInput: false, - customError: false, + customError: hasCustomError, patternMismatch: false, rangeOverflow: false, rangeUnderflow: false, @@ -89,14 +93,16 @@ export default class SlRadioGroup extends LitElement { tooLong: false, tooShort: false, typeMismatch: false, - valid: isValid, - valueMissing: !isValid + valid: hasMissingData || hasCustomError ? false : true, + valueMissing: !hasMissingData }; } reportValidity() { const validity = this.validity; - this.errorMessage = validity.valid ? '' : this.input.validationMessage; + console.log(validity); + + this.errorMessage = this.customErrorMessage || validity.valid ? '' : this.input.validationMessage; this.isInvalid = !validity.valid; if (!validity.valid) { @@ -106,8 +112,9 @@ export default class SlRadioGroup extends LitElement { private preventInvalidSubmit() { this.closest('form')?.addEventListener('submit', e => { + this.reportValidity(); + if (this.isInvalid) { - this.showNativeErrorMessage(); e.preventDefault(); e.stopImmediatePropagation(); }