首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用React表单和Yup验证一个自动完成的多个TextField?

如何使用React表单和Yup验证一个自动完成的多个TextField?
EN

Stack Overflow用户
提问于 2021-11-08 04:13:18
回答 2查看 4.6K关注 0票数 3

我正在使用Material的自动完成多个TextField、React表单和Yup来验证表单输入。

当我将Yup.string()用于daysOfWeek时,即使我选择了值,它也会显示错误消息。但是,如果我将其更改为Yup.array(),则会显示以下错误.

daysOfWeek必须是array类型,但最终值是:null (从值""中强制转换)。如果"null“表示为空值,请确保将模式标记为.nullable()

有什么方法可以让我用Yup来验证资料UI的自动完成多重TextField?提前谢谢你!

这是我的相关密码。

代码语言:javascript
运行
复制
    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>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-08 08:08:49

我做了一个小沙箱,并改变了一些东西让它工作:

  • 您应该使用<Controller />而不是register来实现外部受控元件,就像MUI的<Autocomplete />一样
  • 由于您必须为<Controller/>传递一个<Controller/>(在您的示例中是一个空数组)-然后您可以使用Yup.min方法对数组进行测试,测试用户是否至少选择了一周中的一天,并且摆脱了Yup.required测试,因为他们在您的情况下几乎都是这样做的。
  • 您可以使用helperText<Autocomplete />支柱来显示错误消息。
  • 您可以将ref<Controller />传递给<TextField />inputRef支柱,这样当您提交时不选择一周的一天,它将自动为用户聚焦字段。
代码语言:javascript
运行
复制
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")
});
代码语言:javascript
运行
复制
<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}
        />
      )}
    />
  )}
/>

票数 6
EN

Stack Overflow用户

发布于 2021-11-08 05:54:31

我完成了一个异步、动态和formik自动完成。

这是我的表格文件:

代码语言:javascript
运行
复制
        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>
</>)
    
    }

这是我的自动完成文件:

代码语言:javascript
运行
复制
    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>
                        ),
                    }}
                />
            )}
        />
    );
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69878586

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档