React Hook 表单多下拉验证
React Hook Form Multiple Dropdown Validation
目前我正在使用语义 ui css 多重下拉验证。如何验证下拉菜单,以便用户必须在提交前至少选择一个选项?
目前的输出是,如果我提交表单而不选择任何选项,则会出现错误消息。
但是,如果我选择一个选项并提交,错误信息仍然出现。
以下是我的代码。
import React, { useState } from 'react'
import { Button, Checkbox, Form, Dropdown } from 'semantic-ui-react'
//validation dependencies
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
function TestForm() {
const validationSchema = Yup.object().shape({
firstName: Yup.string()
.required('firstName is required')
.min(6, 'firstName must be at least 6 characters')
,
options: Yup
.object()
.shape({
key: Yup.number().required("key is required (from label)"),
value: Yup.string().required("Value is required")
})
.nullable() // for handling null value when clearing options via clicking "x"
.required("options is required (from outter null check)")
});
const formOptions = { mode: 'all', reValidateMode: 'onChange', resolver: yupResolver(validationSchema) };
const { register, handleSubmit, reset, formState: { errors }, watch, setValue, control } = useForm(formOptions);
const [stateOptions, setStateOptions] = useState([
{
key: 1,
text: 'aaaa',
value: 'a'
},
{
key: 2,
text: 'bbbb',
value: 'b'
},
{
key: 3,
text: 'cccc',
value: 'c'
},
]);
console.log(watch())//For Debugging
const onSubmitHandler = (data) => {
console.log({ data });
setValue('firstName', 'dash', { shouldDirty: true, shouldValidate: true })
}
return (
<div>
<Form reply onSubmit={handleSubmit(onSubmitHandler)}>
<Form.Field>
<label>First Name</label>
<input placeholder='First Name' name="firstName" {...register('firstName')} />
<div className="invalid-feedback">{errors.firstName?.message}</div>
</Form.Field>
<Form.Field>
<Controller
name="options"
control={control}
render={({ field }) => (
<Dropdown
{...field}
placeholder='State'
fluid
multiple
search
selection
options={stateOptions}
/>
)}
/>
<div className="invalid-feedback">{errors.options?.message || errors.options?.value.message}</div>
</Form.Field>
<Form.Field>
<Button type='submit'>Submit</Button>
</Form.Field>
</Form>
</div>
)
}
export default TestForm
由于semantic-ui-react
中的Dropdown
组件不支持ref
属性,所以需要自己控制DropDown
的值,这里举个例子可以试穿:
const options = [
{
key: 1,
text: 'aaaa',
value: 'a',
},
{
key: 2,
text: 'bbbb',
value: 'b',
},
{
key: 3,
text: 'cccc',
value: 'c',
},
]
function TestForm() {
const validationSchema = Yup.object().shape({
firstName: Yup.string()
.required('firstName is required')
.min(6, 'firstName must be at least 6 characters'),
options: Yup.array()
.of(Yup.object()
.shape({
key: Yup.number().required('key is required (from label)'),
value: Yup.string().required('Value is required'),
}))
.test(
"required",
"options is required",
(value) => Array.isArray(value) && value.length > 0
),
});
const formOptions = {
mode: 'all',
reValidateMode: 'onChange',
resolver: yupResolver(validationSchema),
};
const {
register,
handleSubmit,
formState: { errors },
setValue,
control,
} = useForm(formOptions);
const onSubmitHandler = (data) => {
console.log(data);
};
return (
<div>
<Form reply onSubmit={handleSubmit(onSubmitHandler)}>
<Form.Field>
<label>First Name</label>
<input
placeholder="First Name"
name="firstName"
{...register('firstName')}
/>
<div className="invalid-feedback">{errors.firstName?.message}</div>
</Form.Field>
<Form.Field>
<Controller
name="options"
control={control}
render={({ field }) => {
let { value, ...other } = field;
return (
<Dropdown
{...other}
placeholder="State"
fluid
multiple
search
selection
options={options}
value={Array.isArray(value) ? value.map(v => v.value) : []}
onChange={(e,{value})=> {
const values = value.map(v => options.find(item => item.value == v));
setValue('options', values)
}}
/>
);
}}
/>
<div className="invalid-feedback">
{errors.options?.message || errors.options?.value.message}
</div>
</Form.Field>
<Form.Field>
<Button type="submit">Submit</Button>
</Form.Field>
</Form>
</div>
);
}
目前我正在使用语义 ui css 多重下拉验证。如何验证下拉菜单,以便用户必须在提交前至少选择一个选项?
目前的输出是,如果我提交表单而不选择任何选项,则会出现错误消息。
但是,如果我选择一个选项并提交,错误信息仍然出现。
以下是我的代码。
import React, { useState } from 'react'
import { Button, Checkbox, Form, Dropdown } from 'semantic-ui-react'
//validation dependencies
import { useForm, Controller } from "react-hook-form";
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
function TestForm() {
const validationSchema = Yup.object().shape({
firstName: Yup.string()
.required('firstName is required')
.min(6, 'firstName must be at least 6 characters')
,
options: Yup
.object()
.shape({
key: Yup.number().required("key is required (from label)"),
value: Yup.string().required("Value is required")
})
.nullable() // for handling null value when clearing options via clicking "x"
.required("options is required (from outter null check)")
});
const formOptions = { mode: 'all', reValidateMode: 'onChange', resolver: yupResolver(validationSchema) };
const { register, handleSubmit, reset, formState: { errors }, watch, setValue, control } = useForm(formOptions);
const [stateOptions, setStateOptions] = useState([
{
key: 1,
text: 'aaaa',
value: 'a'
},
{
key: 2,
text: 'bbbb',
value: 'b'
},
{
key: 3,
text: 'cccc',
value: 'c'
},
]);
console.log(watch())//For Debugging
const onSubmitHandler = (data) => {
console.log({ data });
setValue('firstName', 'dash', { shouldDirty: true, shouldValidate: true })
}
return (
<div>
<Form reply onSubmit={handleSubmit(onSubmitHandler)}>
<Form.Field>
<label>First Name</label>
<input placeholder='First Name' name="firstName" {...register('firstName')} />
<div className="invalid-feedback">{errors.firstName?.message}</div>
</Form.Field>
<Form.Field>
<Controller
name="options"
control={control}
render={({ field }) => (
<Dropdown
{...field}
placeholder='State'
fluid
multiple
search
selection
options={stateOptions}
/>
)}
/>
<div className="invalid-feedback">{errors.options?.message || errors.options?.value.message}</div>
</Form.Field>
<Form.Field>
<Button type='submit'>Submit</Button>
</Form.Field>
</Form>
</div>
)
}
export default TestForm
由于semantic-ui-react
中的Dropdown
组件不支持ref
属性,所以需要自己控制DropDown
的值,这里举个例子可以试穿:
const options = [
{
key: 1,
text: 'aaaa',
value: 'a',
},
{
key: 2,
text: 'bbbb',
value: 'b',
},
{
key: 3,
text: 'cccc',
value: 'c',
},
]
function TestForm() {
const validationSchema = Yup.object().shape({
firstName: Yup.string()
.required('firstName is required')
.min(6, 'firstName must be at least 6 characters'),
options: Yup.array()
.of(Yup.object()
.shape({
key: Yup.number().required('key is required (from label)'),
value: Yup.string().required('Value is required'),
}))
.test(
"required",
"options is required",
(value) => Array.isArray(value) && value.length > 0
),
});
const formOptions = {
mode: 'all',
reValidateMode: 'onChange',
resolver: yupResolver(validationSchema),
};
const {
register,
handleSubmit,
formState: { errors },
setValue,
control,
} = useForm(formOptions);
const onSubmitHandler = (data) => {
console.log(data);
};
return (
<div>
<Form reply onSubmit={handleSubmit(onSubmitHandler)}>
<Form.Field>
<label>First Name</label>
<input
placeholder="First Name"
name="firstName"
{...register('firstName')}
/>
<div className="invalid-feedback">{errors.firstName?.message}</div>
</Form.Field>
<Form.Field>
<Controller
name="options"
control={control}
render={({ field }) => {
let { value, ...other } = field;
return (
<Dropdown
{...other}
placeholder="State"
fluid
multiple
search
selection
options={options}
value={Array.isArray(value) ? value.map(v => v.value) : []}
onChange={(e,{value})=> {
const values = value.map(v => options.find(item => item.value == v));
setValue('options', values)
}}
/>
);
}}
/>
<div className="invalid-feedback">
{errors.options?.message || errors.options?.value.message}
</div>
</Form.Field>
<Form.Field>
<Button type="submit">Submit</Button>
</Form.Field>
</Form>
</div>
);
}