123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257import React,{ ReactElement, useEffect, useState }from"react";import{ Controller, useForm }from"react-hook-form";import{ Button }from"@react-md/button";import{ DialogFooter }from"@react-md/dialog";import{
Checkbox,
Fieldset,
Form,
FormMessage,
Radio,
Select,
Switch,}from"@react-md/form";import{ CircularProgress }from"@react-md/progress";import{ useTimeout }from"@react-md/utils";import ControllerTextField,{ ExampleFormData }from"./ControllerTextField";interfaceState{
loading:boolean;
data: ExampleFormData |null;}constEMAIL_PATTERN=/^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;const titles =["Mr","Mrs","Miss","Dr","Other"];/**
* The entire form is in this single file to keep the example simple, but it is
* recommended to separate these components or other recommendations from the
* main react-hook-form documentation: https://react-hook-form.com/
*
* Since all of the `react-md` components forward the `ref` prop automatically,
* all that's required for most form components is using the `Controller`
* component from `react-hook-form` and initializing the
* `defaulValue`/`defaultChecked`. The only components that do not follow this
* pattern are the `Radio` and `Select` components where you'll want to use the
* `render` prop from the `Controller` instead.
*
* The `Radio` component uses the `render` prop since the `error` state doesn't
* seem to work correctly (might just be because I haven't used this library
* outside of this demo).
*
* The `Select` compoent uses the `render` prop just because of a `Typescript`
* error that the `value` and `onChange` props are required. Both of those props
* are injected by the `Controller` component, but using the `render` fixes this
* compiler error.
*/exportdefaultfunctionDemo(): ReactElement {const{
control,
reset,
handleSubmit,
formState:{
errors:{ firstName, lastName, email, phone, title, developer },},}=useForm<ExampleFormData>({ mode:"onChange"});const[{ data, loading }, setState]=useState<State>({
loading:false,
data:null,});const[start]=useTimeout(()=>{setState((prevState)=>({ loading:false, data: prevState.data }));},10000);useEffect(()=>{if(loading){start();}},[loading, start]);return(<><FormonReset={()=>{setState({ loading:false, data:null});reset({
firstName:"",
lastName:"",
email:"",
phone:"",
title:"",
developer:"",
cool:"",
save:"",});}}onSubmit={handleSubmit((data)=>setState({ data, loading:true}))}><ControllerTextFieldid="rhf-first-name"name="firstName"label="First Name"placeholder="John"control={control}rules={{
required:"Required",
maxLength:{
value:10,
message:"Max length is 10",},}}error={!!firstName}message={firstName?.message}/><ControllerTextFieldid="rhf-last-name"name="lastName"label="Last Name"placeholder="Doe"control={control}rules={{
required:"Required",
minLength:{
value:2,
message:"Min length is 2",},}}error={!!lastName}message={lastName?.message}/><ControllerTextFieldid="rhf-email"name="email"type="email"label="Email"placeholder="john.doe@email.com"control={control}rules={{
required:"Required",
pattern:{
value:EMAIL_PATTERN,
message:"Invalid email address",},}}pattern={EMAIL_PATTERN.source}error={!!email}message={email?.message}/><ControllerTextFieldcontrol={control}id="rhf-phone"name="phone"type="tel"label="Mobile Phone"placeholder="123 4567"rules={{
required:"Required",
minLength:{
value:7,
message:"At least 7 characters",},
maxLength:{
value:11,
message:"No more than 11 characters",},}}error={!!phone}message={phone?.message}/><Controllercontrol={control}name="title"defaultValue=""rules={{ required:"Cannot be blank"}}render={({ field })=>(<Select{...field}id="rhf-title"aria-describedby="rhf-title-error"label="Title"placeholder="Title"options={titles}error={!!title}/>)}/><FormMessageid="rh-title-error"error>{title?.message}</FormMessage><Fieldsetlegend="Are you a developer?"><Controllercontrol={control}name="developer"rules={{ required:"Required"}}render={({ field })=>(<Radio{...field}id="rhf-developer-yes"label="Yes"error={!!developer}value="yes"/>)}/><Controllercontrol={control}name="developer"rules={{ required:"Required"}}render={({ field })=>(<Radio{...field}id="rhf-developer-no"label="No"error={!!developer}value="no"/>)}/></Fieldset><Controllercontrol={control}name="cool"render={({ field })=>(<Checkbox{...field}id="rhf-cool"label="Are you cool?"/>)}/><Controllercontrol={control}name="save"render={({ field })=>(<Switch{...field}id="rhf-save"label="Save?"defaultChecked/>)}/><DialogFooteralign="end"><Buttonid="rhf-reset"type="reset"theme="secondary"themeType="outline">
Reset
</Button><Buttonid="rhf-submit"type={loading ?"button":"submit"}theme={loading ?"disabled":"primary"}themeType="outline"aria-label={loading ?"Submitting":undefined}>{loading ?(<CircularProgressid="rhf-submit-progress"centered={false}/>):("Submit")}</Button></DialogFooter></Form>{data &&(<pre><code>{JSON.stringify(data,null,2)}</code></pre>)}</>);}