我正在使用Material的自动完成多个TextField、React表单和Yup来验证表单输入。
当我将Yup.string()用于daysOfWeek时,即使我选择了值,它也会显示错误消息。但是,如果我将其更改为Yup.array(),则会显示以下错误.
daysOfWeek必须是
array
类型,但最终值是:null
(从值""
中强制转换)。如果"null“表示为空值,请确保将模式标记为.nullable()
有什么方法可以让我用Yup来验证资料UI的自动完成多重TextField?提前谢谢你!
这是我的相关密码。
const [selected, setSelected] = useState([]);
const validationSchema = Yup.object().shape({
daysOfWeek: Yup.string()
.required("Days of the week are required")
});
const {
formState: {errors},
handleSubmit,
register
} = useForm({
resolver: yupResolver(validationSchema)
});
<Autocomplete
disableClearable
disablePortal
filterSelectedOptions
multiple
getOptionDisabled={(option) => option.disabled ? true : false}
getOptionLabel={(option) => option.label}
id="days-autocomplete"
onChange={(event, value) => onOptionsChange(event, value)}
options={daysOfWeekSuggestions}
renderInput={(params) => <TextField
required
error={errors.daysOfWeek ? true : false}
id="daysOfWeek"
label="Days of the week"
name="daysOfWeek"
type="search"
{...params}
{...register("daysOfWeek")}
/>}
value={selected}
/>
<Typography color="error" sx={errorSx} variant="inherit">{errors.daysOfWeek?.message}</Typography>
发布于 2021-11-08 08:08:49
我做了一个小沙箱,并改变了一些东西让它工作:
<Controller />
而不是register
来实现外部受控元件,就像MUI的<Autocomplete />
一样<Controller/>
传递一个<Controller/>
(在您的示例中是一个空数组)-然后您可以使用Yup.min
方法对数组进行测试,测试用户是否至少选择了一周中的一天,并且摆脱了Yup.required
测试,因为他们在您的情况下几乎都是这样做的。helperText
的<Autocomplete />
支柱来显示错误消息。ref
从<Controller />
传递给<TextField />
的inputRef
支柱,这样当您提交时不选择一周的一天,它将自动为用户聚焦字段。const validationSchema = Yup.object().shape({
daysOfWeek: Yup.array()
.of(
Yup.object().shape({
value: Yup.string(),
label: Yup.string()
})
)
.min(1, "Days of the week are required")
});
<Controller
name="daysOfWeek"
control={control}
defaultValue={[]}
render={({ field: { ref, ...field }, fieldState: { error } }) => (
<Autocomplete
{...field}
disableClearable
disablePortal
filterSelectedOptions
multiple
getOptionDisabled={(option) => option.disabled}
getOptionLabel={(option) => option.label}
id="days-autocomplete"
onChange={(event, value) => field.onChange(value)}
options={daysOfWeekSuggestions}
renderInput={(params) => (
<TextField
required
error={!!error}
helperText={error?.message}
id="daysOfWeek"
label="Days of the week"
name="daysOfWeek"
type="search"
inputRef={ref}
{...params}
/>
)}
/>
)}
/>
发布于 2021-11-08 05:54:31
我完成了一个异步、动态和formik自动完成。
这是我的表格文件:
const FormSimple = (props) => {
const validationSchema = Yup.object().shape({
name: Yup.string()
.min(2, 'Too Short!')
.max(50, 'Too Long!')
.required('Required'),
nationalId: Yup.number("Invalid Number")
.min(2, 'Too Short!')
.max(9999999999, 'Too Long!')
.required('Required'),
correspEmail: Yup.string().email('Invalid email'),
financeNationalNo: Yup.number(),
});
const formik = useFormik({
initialValues: details,
validationSchema: validationSchema,
onSubmit: (values) => {
if (id !== "new")
editData(values)
else
sendData(values)
},
});
return (<>
<form onSubmit={formik.handleSubmit}>
<div className="row">
<InputSize>
<Asynchronous getListData={getListCountry} onChange={(value)=> {
formik.setFieldValue("registrationCountryName",value.nameEn)
formik.setFieldValue("registrationCountryId",value.id)
}} name="nameEn"
defaultValue={formik.values?.registrationCountryName ? {
nameEn: formik.values?.registrationCountryName,
id: formik.values?.registrationCountryId
} : null}
value={formik.values?.registrationCountryName ? {
nameEn: formik.values?.registrationCountryName,
id: formik.values?.registrationCountryId
} : null}
required={true}
showName="Country Of Registration" label="nameEn" id="id"/>
</InputSize>
<div className="col-12 mt-4">
<Button variant="contained" color="primary" type="submit"
disabled={loading}>Submit</Button>
</div>
</div>
</form>
</>)
}
这是我的自动完成文件:
import * as React from 'react';
import TextField from '@mui/material/TextField';
import Autocomplete from '@mui/material/Autocomplete';
import CircularProgress from '@mui/material/CircularProgress';
import {useRef} from "react";
export default function Asynchronous(props) {
const {onChange, name, getListData, label = "name", id = "id", showName,defaultValue,disabled,required,value,noOption="No Option"} = props;
const [open, setOpen] = React.useState(false);
const [options, setOptions] = React.useState([]);
const [filters, setFilters] = React.useState(null);
const [loadingApi, setLoadingApi] = React.useState(false)
const loading = open && options.length === 0;
let timeOut = useRef(null);
const getData = async (search = "") => {
setLoadingApi(true)
const data = await getListData(search); // For demo purposes.
// console.log(data)
setLoadingApi(false);
// console.log(data)
if(data)
setOptions([...data]);
}
React.useEffect(() => {
if (!loading) {
return undefined;
}
getData();
}, [loading]);
React.useEffect(() => {
if (filters !== null) {
if (timeOut.current !== null)
clearTimeout(timeOut.current);
timeOut.current = setTimeout(() => getData(filters), 500);
}
}, [filters]);
React.useEffect(() => {
if (!open) {
setOptions([]);
}
}, [open]);
return (
<Autocomplete
disabled={disabled}
id={name}
name={name}
sx={{width: "100%"}}
open={open}
onOpen={() => {
setOpen(true);
}}
onClose={() => {
setOpen(false);
}}
defaultValue={defaultValue}
value={value}
isOptionEqualToValue={(option, value) => option?.[id] === value?.[id]}
getOptionLabel={(option) => option?.[label]}
options={options}
onChange={(e, value) => onChange(value)}
loading={loadingApi}
noOptionsText={noOption}
renderInput={(params) => (
<TextField
name={name}
required={required}
variant="standard"
{...params}
label={showName}
onChange={(e) => setFilters(e.target.value)}
InputProps={{
...params.InputProps,
onblur:() => {},
endAdornment: (
<React.Fragment>
{loadingApi ? <CircularProgress color="inherit" size={20}/> : null}
{params.InputProps.endAdornment}
</React.Fragment>
),
}}
/>
)}
/>
);
}
https://stackoverflow.com/questions/69878586
复制相似问题