最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Yup validation of an array - values required only if array length is bigger than 1 - Stack Overflow

programmeradmin0浏览0评论

I have 2 dropdowns in each row and I can dynamically add and remove rows apart form the first one. I would like to submit form if there is only one row (rendered from the beginning) and it is empty and not be able to submit if:

  • value1 is selected without value 2

or

  • a new row is added but has no value selected

I am using yup validation.

I have tried with checking the length with .test(), but this test run always after checking 'required'.

This is what I would like to have:

const validationSchema = yup.object({
values:
    yup.array()
        .of(
            yup.object({
                value1: yup.string().required(), // ONLY IF ARRAY LENGTH > 1
                value2: yup.string().required()// ONLY IF VALUE1 IS SELECTED
            })
        )});

I have 2 dropdowns in each row and I can dynamically add and remove rows apart form the first one. I would like to submit form if there is only one row (rendered from the beginning) and it is empty and not be able to submit if:

  • value1 is selected without value 2

or

  • a new row is added but has no value selected

I am using yup validation.

I have tried with checking the length with .test(), but this test run always after checking 'required'.

This is what I would like to have:

const validationSchema = yup.object({
values:
    yup.array()
        .of(
            yup.object({
                value1: yup.string().required(), // ONLY IF ARRAY LENGTH > 1
                value2: yup.string().required()// ONLY IF VALUE1 IS SELECTED
            })
        )});
Share Improve this question asked Jan 5, 2022 at 8:25 AggatAggat 731 silver badge8 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 4

If I understand you correctly, then this should do.

const mySchema = yup.object({
  values: yup.array().of(
    yup.object({
      value1: yup
        .string()
        .test(
          "test-1",
          "error: required if array length > 1",
          (value, context) => {
            const [, values] = context.from;
            const {
              value: { values: arrayValues }
            } = values;
            // ONLY IF ARRAY LENGTH > 1
            if (arrayValues.length > 1) {
              // valid only if value is provided
              return !!value;
            }
          }
        ),
      value2: yup.string().when("value1", {
        // if value1 is provied, value2 should be provided too
        is: (value1) => !!value1,
        then: (value2) => value2.required()
      })
    })
  )
});
 // should pass
  console.log(
    mySchema.validateSync({
      values: [
        { value1: "1", value2: "2" },
        { value1: "1", value2: "2" }
      ]
    })
  );
  // ValidationError: error: required if array length > 1
  console.log(
    mySchema.validateSync({
      values: [{ value1: "1", value2: "2" }, { value2: "2" }]
    })
  );

  // ValidationError: values[1].value2 is a required field
  console.log(
    mySchema.validateSync({
      values: [{ value1: "1", value2: "2" }, { value1: "1" }]
    })
  );

The key thing here is to remove .required() and provide your own check in test() when the array meets your custom condition.

to access the parent value inside of .test(), use context.from

const [parent1, parent2, ...rest] = context.from;

Live Example

发布评论

评论列表(0)

  1. 暂无评论