简体   繁体   English

用 yup 进行条件验证

[英]conditional validation with yup

I have 3 fields in a form, the "type" field is select and from that list, some items enable or disable the "out" field, if is enable I need the "out" field to be less than the "in" field and vice-versa, but if the "out" field is disabled I don't need that validation, I was trying something with.when, but is not working, any ideas on how to do this?我在一个表单中有 3 个字段,“类型”字段是 select,从该列表中,一些项目启用或禁用“输出”字段,如果启用,我需要“输出”字段小于“输入”字段反之亦然,但如果“out”字段被禁用,我不需要验证,我正在尝试一些东西。什么时候,但没有工作,关于如何做到这一点的任何想法?

  const [disableOutCounterField, setDisableOutCounterField] = useState(false);

  const schema = yup.object().shape({
    type: yup.string().required(requiredMessage),
    in: yup
      .number(numberMessage)
      .required(requiredMessage)
      .integer(integerMessage)
      .min(1, positiveMessage)
      .typeError(numberMessage)
      .when("out", {
        is: !disableOutCounterField,
        then: yup.number().moreThan(yup.ref("out"), moreThanMessage),
        message: moreThanMessage,
      }),
    out: yup
      .number(numberMessage)
      .integer(integerMessage)
      .typeError(numberMessage)
      .lessThan(yup.ref("in"), lessThanMessage),
  });

The construct:构造:

.when("out", {
  is: !disableOutCounterField,

compares the out value with !disableOutCounterField , and if they are equal, the then rule is applied.out值与!disableOutCounterField进行比较,如果它们相等,则应用then规则。 But quite likely they are never the same.但很可能它们永远不会相同。

The check that is needed here is just the value of !disableOutCounterField by itself, for any value of out .对于out的任何值,此处需要的检查只是!disableOutCounterField本身的值。 This can be done using an expression:这可以使用表达式来完成:

.when("out", {
  is: value => !disableOutCounterField,

In words: for every out value, return !disableOutCounterField , and if it returns true, apply the then part.换句话说:对于每个out值,返回!disableOutCounterField ,如果它返回 true,则应用then部分。

An alternative I found for this is to regenerate the object validationSchema from inside a useEffect .我为此找到的另一种方法是从 useEffect 中重新生成useEffect validationSchema

This has the benefit of using useState without having them mapped to specific form fields ahead of time, such as if you set something conditionally from the database and don't want to set it as a hidden field somewhere.这有使用useState的好处,而无需提前将它们映射到特定的表单字段,例如,如果您有条件地从数据库中设置某些内容并且不想将其设置为某处的隐藏字段。

const validationPiece = yup.object({
amount: yup
  .number()
  .typeError('Please enter an amount')
  .required('Please enter an amount')
});

const [validationSchema, setValidaitonSchema] = useState(yup.object({}));

const {
  register,
  handleSubmit,
  reset,
  formState: { errors },
} = useForm({
  resolver: yupResolver(validationSchema),
});

useEffect(() => {
  if (needNewPartOfForm) {
    const validationSchemaDict = {};
    if (needNewPartOfForm.xyz) {
      validationSchemaDict['xyz'] = validationPiece; // does this need a cloneDeep?
    }
    if (needNewPartOfForm.abc) {
      validationSchemaDict['abc'] = validationPiece;
    }
    setValidaitonSchema(yup.object(validationSchemaDict));
  }
}, [clientDocs, clientId, reset, teamId]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM