Demonstrates the use of form inputs using a third party react form library.
By default, form input components leverage the browser’s formdata event and constraint validation API . However you can easily use the inputs components in conjunction with a React form library. In this context, you are no longer using the browser’s default capabilities but are instead relying on the library in question to handle form data and validation events. This means you will need suppress client side validation by adding novalidate to the surrounding <form > element.
The following example demonstrates using form inputs with React Hook Form . Since the library itself is responsible for validation, you will see that novalidate is added to the form element and that the errorText property is leveraged to pass in the appropriate error message when it’s present.
import { useState, useEffect } from "react";import { useForm, Controller } from "react-hook-form"import { OdsInput } from '@ods/components/react.input';import { OdsButton } from '@ods/components/react.button';import { OdsSelect } from '@ods/components/react.select';import { OdsOption } from '@ods/components/react.option';import { OdsCheckbox } from '@ods/components/react.checkbox';import { OdsRadioGroup } from '@ods/components/react.radio-group';import { OdsRadio } from '@ods/components/react.radio';import { OdsTextarea } from '@ods/components/react.textarea';
const Example = () => { const [formData, setFormData] = useState('');
// We supply defaultValues so on reset, the HTML native reset API isn't invoked. const { handleSubmit, reset, formState: { errors }, control, register } = useForm({ reValidateMode: 'onBlur', defaultValues: { input1: '', input2: '', input3: '', input4: false, input5: false } });
const onSubmit = (data:object) => { const formattedData = JSON.stringify(data);
setFormData(formattedData); };
return ( <div ods-layout="block gap:lg align:stretch"> <form noValidate id="form-test" onSubmit={handleSubmit(onSubmit)}> <div ods-layout="block gap:lg align:stretch"> <div ods-layout="block gap:lg"> <div ods-layout="inline gap:md stretch"> <OdsInput label="Input 1" helpText="help text" errorText={errors?.input1?.message} {...register("input1", { required: "Input 1 is required" })} /> </div>
<div ods-layout="inline gap:md stretch"> <OdsSelect clearable label="Select one" helpText="help text" errorText={errors?.input2?.message} {...register("input2", { required: "Input 2 is required" })} > <OdsOption value="option-1">Option 1</OdsOption> <OdsOption value="option-2">Option 2</OdsOption> <OdsOption value="option-3">Option 3</OdsOption> </OdsSelect> </div>
<div ods-layout="inline gap:md stretch"> <OdsTextarea label="Comments" helpText="help text" errorText={errors?.input3?.message} {...register("input3", { required: "Input 3 is required." })} > </OdsTextarea> </div>
<Controller name="input4" control={control} rules={{ required: 'Input 4 is required' }} render={({ field: { onChange, onBlur } }) => ( <OdsCheckbox value="yes" helpText="help text" errorText={errors?.input4?.message} onOdsBlur={onBlur} onOdsChange={(e) => onChange((e.target as HTMLInputElement).checked || '')} > Check me before submitting </OdsCheckbox> )} />
<Controller name="input5" control={control} rules={{ required: 'Input 5 is required' }} render={({ field: { onChange, onBlur } }) => ( <OdsRadioGroup label="Select an option" helpText="help text" errorText={errors?.input5?.message} onOdsChange={(e) => onChange((e.target as HTMLInputElement).value || '')} > <OdsRadio value="1" onOdsBlur={onBlur}>Patient 1</OdsRadio> <OdsRadio value="2" onOdsBlur={onBlur}>Patient 2</OdsRadio> </OdsRadioGroup> )} />
<div ods-layout="inline gap:md"> <OdsButton type="submit" variant="primary">Submit</OdsButton> <OdsButton type="reset" onClick={() => reset()}>Reset</OdsButton> </div> </div> </div> </form>
{!Object.keys(errors).length && formData ? <p className="text-base">Form Data: {formData}</p> : <p className="text-base">You cannot submit form data until all fields are filled out.</p>} </div> );}
export default Example;