是的,react-hook-form:如何在表单中创建条件必填字段?
Yup and react-hook-form: how to create conditional mandatory fields in a form?
阿门德
我有一个使用 Material UI、react-hook-from 和是的表单。
表单包含三组无线电组(例如:radio-g1、radio-g2、radio-g3),并且用户必须 select radio-g1、radio-g2 中的至少两个选项.此外,如果他们从 radio-g2 选择选项 'other',将显示另一个必填字段 radio-g3。
最后,radio-g3 在隐藏时不是强制性的。
如有任何帮助,我们将不胜感激。
这是一些示例代码:
const schema = yup.object().shape({
radioG1: yup.string().required("Please select an Avenger"),
radioG2: yup.string().required("Please select an Avenger"),
radioG3: yup.string().required("Please select an Avenger")
});
const App = () => {
const [show, setShow] = useState(false);
const methods = useForm({
mode: "all",
shouldUnregister: true,
resolver: yupResolver(schema)
});
const {
handleSubmit,
control,
formState: { errors }
} = methods;
const onSubmit = (data) => {
alert(JSON.stringify(data));
};
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG1}
>
<FormLabel component="legend">Favorite Avengers:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Iron Man"
control={<Radio />}
label="Iron Man"
/>
<FormControlLabel
value="Captain America"
control={<Radio />}
label="Captain America"
/>
</RadioGroup>
)}
name="radioG1"
control={control}
/>
{errors.radioG1 ? (
<FormHelperText>{errors?.radioG1?.message}</FormHelperText>
) : null}
</FormControl>
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG2}
>
<FormLabel component="legend">Favorite Avengers 2:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Thor"
control={<Radio />}
label="Thor"
/>
<FormControlLabel
value="Black Widow"
control={<Radio />}
label="Black Widow"
/>
</RadioGroup>
)}
name="radioG2"
control={control}
/>
{errors.radioG2 ? (
<FormHelperText>{errors?.radioG2?.message}</FormHelperText>
) : null}
</FormControl>
</div>
<Box mt={2} mb={2}>
<Alert severity="info">
<Link
color="primary"
underline="always"
component="button"
onClick={() => setShow(!show)}
>
Meh, I don't like these Avengers, SHOW MORE.
</Link>
</Alert>
{show ? <OtherAvengers control={control} errors={errors} /> : null}
</Box>
<Box>
<Button
size="large"
variant="contained"
type="submit"
color="primary"
>
Submit
</Button>
</Box>
</form>
</FormProvider>
);
};
const OtherAvengers = ({ control, errors }) => {
return (
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG3}
>
<FormLabel component="legend">Favorite Avengers 3:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel value="Hulk" label="Hulk" control={<Radio />} />
<FormControlLabel
value="Ant-Man"
label="Ant-Man"
control={<Radio />}
/>
</RadioGroup>
)}
name="radioG3"
control={control}
/>
{errors.radioG3 ? (
<FormHelperText>{errors?.radioG3?.message}</FormHelperText>
) : null}
</FormControl>
</div>
);
};
Codesandbox 在这里 https://codesandbox.io/s/conditional-mandatory-fields-7xojm?file=/src/index.jsx
您可以使用 when() 并将您的 radioG1
、radioG2
和 radioG3
传递给条件。
像这样:
let schema = yup.object({
isBig: yup.boolean(),
count: yup.number().when('isBig', (isBig, schema) => {
return isBig ? schema.min(5) : schema.min(0);
}),
});
根据上面@Ryan Le 的回答,这里是工作代码:
const schema = yup.object().shape({
radioG1: yup.string().required("Please select an Avenger"),
radioG2: yup.string().required("Please select an Avenger"),
radioG3: yup.string().when("radioG2", {
is: "other",
then: yup.string().required('can\'t be blank')
})
});
const App = () => {
const methods = useForm({
mode: "all",
shouldUnregister: true,
resolver: yupResolver(schema)
});
const {
handleSubmit,
control,
watch,
formState: { errors }
} = methods;
let watchOther = watch("radioG2");
const onSubmit = (data) => {
alert(JSON.stringify(data));
};
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG1}
>
<FormLabel component="legend">Favorite Avenger:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Iron Man"
control={<Radio />}
label="Iron Man"
/>
<FormControlLabel
value="Captain America"
control={<Radio />}
label="Captain America"
/>
</RadioGroup>
)}
name="radioG1"
control={control}
/>
{errors.radioG1 ? (
<FormHelperText>{errors?.radioG1?.message}</FormHelperText>
) : null}
</FormControl>
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG2}
>
<FormLabel component="legend">Favorite Avenger 2:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Thor"
control={<Radio />}
label="Thor"
/>
<FormControlLabel
value="Black Widow"
control={<Radio />}
label="Black Widow"
/>
<FormControlLabel
value="other"
control={<Radio />}
label="Other"
/>
</RadioGroup>
)}
name="radioG2"
control={control}
/>
{errors.radioG2 ? (
<FormHelperText>{errors?.radioG2?.message}</FormHelperText>
) : null}
</FormControl>
</div>
{watchOther === "other" ? (
<OtherAvengers control={control} errors={errors} />
) : null}
<Box>
<Button
size="large"
variant="contained"
type="submit"
color="primary"
>
Submit
</Button>
</Box>
</form>
</FormProvider>
);
};
const OtherAvengers = ({ control, errors }) => {
return (
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG3}
>
<FormLabel component="legend">Favorite Avenger 3:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel value="Hulk" label="Hulk" control={<Radio />} />
<FormControlLabel
value="Ant-Man"
label="Ant-Man"
control={<Radio />}
/>
</RadioGroup>
)}
name="radioG3"
control={control}
/>
{errors.radioG3 ? (
<FormHelperText>{errors?.radioG3?.message}</FormHelperText>
) : null}
</FormControl>
</div>
);
};
阿门德
我有一个使用 Material UI、react-hook-from 和是的表单。
表单包含三组无线电组(例如:radio-g1、radio-g2、radio-g3),并且用户必须 select radio-g1、radio-g2 中的至少两个选项.此外,如果他们从 radio-g2 选择选项 'other',将显示另一个必填字段 radio-g3。
最后,radio-g3 在隐藏时不是强制性的。
如有任何帮助,我们将不胜感激。 这是一些示例代码:
const schema = yup.object().shape({
radioG1: yup.string().required("Please select an Avenger"),
radioG2: yup.string().required("Please select an Avenger"),
radioG3: yup.string().required("Please select an Avenger")
});
const App = () => {
const [show, setShow] = useState(false);
const methods = useForm({
mode: "all",
shouldUnregister: true,
resolver: yupResolver(schema)
});
const {
handleSubmit,
control,
formState: { errors }
} = methods;
const onSubmit = (data) => {
alert(JSON.stringify(data));
};
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG1}
>
<FormLabel component="legend">Favorite Avengers:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Iron Man"
control={<Radio />}
label="Iron Man"
/>
<FormControlLabel
value="Captain America"
control={<Radio />}
label="Captain America"
/>
</RadioGroup>
)}
name="radioG1"
control={control}
/>
{errors.radioG1 ? (
<FormHelperText>{errors?.radioG1?.message}</FormHelperText>
) : null}
</FormControl>
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG2}
>
<FormLabel component="legend">Favorite Avengers 2:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Thor"
control={<Radio />}
label="Thor"
/>
<FormControlLabel
value="Black Widow"
control={<Radio />}
label="Black Widow"
/>
</RadioGroup>
)}
name="radioG2"
control={control}
/>
{errors.radioG2 ? (
<FormHelperText>{errors?.radioG2?.message}</FormHelperText>
) : null}
</FormControl>
</div>
<Box mt={2} mb={2}>
<Alert severity="info">
<Link
color="primary"
underline="always"
component="button"
onClick={() => setShow(!show)}
>
Meh, I don't like these Avengers, SHOW MORE.
</Link>
</Alert>
{show ? <OtherAvengers control={control} errors={errors} /> : null}
</Box>
<Box>
<Button
size="large"
variant="contained"
type="submit"
color="primary"
>
Submit
</Button>
</Box>
</form>
</FormProvider>
);
};
const OtherAvengers = ({ control, errors }) => {
return (
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG3}
>
<FormLabel component="legend">Favorite Avengers 3:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel value="Hulk" label="Hulk" control={<Radio />} />
<FormControlLabel
value="Ant-Man"
label="Ant-Man"
control={<Radio />}
/>
</RadioGroup>
)}
name="radioG3"
control={control}
/>
{errors.radioG3 ? (
<FormHelperText>{errors?.radioG3?.message}</FormHelperText>
) : null}
</FormControl>
</div>
);
};
Codesandbox 在这里 https://codesandbox.io/s/conditional-mandatory-fields-7xojm?file=/src/index.jsx
您可以使用 when() 并将您的 radioG1
、radioG2
和 radioG3
传递给条件。
像这样:
let schema = yup.object({
isBig: yup.boolean(),
count: yup.number().when('isBig', (isBig, schema) => {
return isBig ? schema.min(5) : schema.min(0);
}),
});
根据上面@Ryan Le 的回答,这里是工作代码:
const schema = yup.object().shape({
radioG1: yup.string().required("Please select an Avenger"),
radioG2: yup.string().required("Please select an Avenger"),
radioG3: yup.string().when("radioG2", {
is: "other",
then: yup.string().required('can\'t be blank')
})
});
const App = () => {
const methods = useForm({
mode: "all",
shouldUnregister: true,
resolver: yupResolver(schema)
});
const {
handleSubmit,
control,
watch,
formState: { errors }
} = methods;
let watchOther = watch("radioG2");
const onSubmit = (data) => {
alert(JSON.stringify(data));
};
return (
<FormProvider {...methods}>
<form onSubmit={handleSubmit(onSubmit)}>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG1}
>
<FormLabel component="legend">Favorite Avenger:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Iron Man"
control={<Radio />}
label="Iron Man"
/>
<FormControlLabel
value="Captain America"
control={<Radio />}
label="Captain America"
/>
</RadioGroup>
)}
name="radioG1"
control={control}
/>
{errors.radioG1 ? (
<FormHelperText>{errors?.radioG1?.message}</FormHelperText>
) : null}
</FormControl>
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG2}
>
<FormLabel component="legend">Favorite Avenger 2:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel
value="Thor"
control={<Radio />}
label="Thor"
/>
<FormControlLabel
value="Black Widow"
control={<Radio />}
label="Black Widow"
/>
<FormControlLabel
value="other"
control={<Radio />}
label="Other"
/>
</RadioGroup>
)}
name="radioG2"
control={control}
/>
{errors.radioG2 ? (
<FormHelperText>{errors?.radioG2?.message}</FormHelperText>
) : null}
</FormControl>
</div>
{watchOther === "other" ? (
<OtherAvengers control={control} errors={errors} />
) : null}
<Box>
<Button
size="large"
variant="contained"
type="submit"
color="primary"
>
Submit
</Button>
</Box>
</form>
</FormProvider>
);
};
const OtherAvengers = ({ control, errors }) => {
return (
<div>
<FormControl
variant="outlined"
component="fieldset"
margin="normal"
error={!!errors.radioG3}
>
<FormLabel component="legend">Favorite Avenger 3:</FormLabel>
<Controller
render={({ field }) => (
<RadioGroup {...field}>
<FormControlLabel value="Hulk" label="Hulk" control={<Radio />} />
<FormControlLabel
value="Ant-Man"
label="Ant-Man"
control={<Radio />}
/>
</RadioGroup>
)}
name="radioG3"
control={control}
/>
{errors.radioG3 ? (
<FormHelperText>{errors?.radioG3?.message}</FormHelperText>
) : null}
</FormControl>
</div>
);
};