javascript - 使用 Yup.ref 和 .test 根据多个相关字段值验证 Yup 中的字段

标签 javascript reactjs validation formik yup

我在“react”中创建了一个多步骤表单:“^17.0.1”、“yup”:“^0.29.3”和“formik”:“^2.2.3”。

我想检查用户输入的生日 (dobD) 根据出生月份 (dobM) 和出生年份 (dobY) 是否有效。

我有 3 个独立的输入。 dobM, dobD, dobY

dobD 的第一次检查有效(即用户只能输入 1 到 31 之间的值)但是如果它是少于 31 天的月份(例如 6 月或 9 月)或者如果月份是二月(除了闰年只有 28 天)。

我尝试使用 Yup.ref 在日期字段验证中引用年和月字段,但是如果我输入 04 月份,用户仍然可以输入 31,这是不正确的(因为四月 (04) 只有 30天)。

有什么办法可以解决这个问题吗?谢谢!

这是我目前正在使用的 Yup 中的验证:

  // Step 3: Date of Birth
  Yup.object().shape({
    dobM: Yup.string()
      .test(
        'dobM',
        'Invalid Month',
        value => {
          if (value < 1 || value > 12) {
            return false;
          }
          return true;
        }
      )
      .min(2, 'Invalid')
      .max(2, 'Invalid')
      .required('Required'),
    dobY: Yup.string()
      .test(
        'dobY',
        'Valid Year required',
        value => {
          const today = new Date();
          const adultYear = today.getFullYear() - 17;
          if (value < 1900 || value > adultYear) {
            return false;
          }
          return true;
        }
      )
      .min(4, 'Must be 4 digits')
      .max(4, 'Must be 4 digits')
      .required('Valid Year required'),
    dobD: Yup.string()
      .test(
        'dobD',
        'Invalid Day',
        value => {
          if (value < 1 || value > 31) {
            return false;
          }

          // Check months with less than 31 days - DOESNT WORK
          // 4. April
          // 6. June
          // 9. September
          // 11. November
          if ((Yup.ref('dobM') == 4 || Yup.ref('dobM') == 6 || Yup.ref('dobM') == 9 || Yup.ref('dobM') == 11) && value == 31) {
            return false;
          }

          // If February - DOESNT WORK
             if (Yup.ref('dobM') == 2) {
             const isLeapYear = Yup.ref('dobY') % 4 == 0 && (Yup.ref('dobY') % 100 != 0 || Yup.ref('dobY') % 400 == 0);

             if (day > 29 || (day == 29 && !isLeapYear)) {
               return false;
             }
           }

          return true;
        }
      )
      .min(2, 'Invalid')
      .max(2, 'Invalid')
      .required('Required'),  
  }), 

最佳答案

发布我的解决方案,希望这对其他人有帮助。

我错误地使用了 Yup.ref(Yup.ref('fieldname') 是一个对象,而不是单个值)。

** 为了能够访问 Yup 中的另一个字段,我在测试中从箭头函数转换为常规函数,然后可以使用访问字段值

this.options.parent.FIELD_NAME

在这个例子中看到:

function(day) {
          const month = this.options.parent.dobM;
          const year = this.options.parent.dobY;
 
         // check whatever you want with the value of month and year
}

完整的 DOB 验证:

  // Step 3: Date of Birth
  Yup.object().shape({
    dobM: Yup.string()
      .matches(/^(0[1-9]|1[012])$/, 'Invalid Month')
      .test(
        'dobM',
        'Invalid Month',
        value => {
          if (value < 1 || value > 12) {
            return false;
          }
          return true;
        }
      )
      .min(2, 'Invalid')
      .max(2, 'Invalid')
      .required('Required'),
    dobY: Yup.string()
      .test(
        'dobY',
        'Valid Year required',
        value => {
          const today = new Date();
          const adultYear = today.getFullYear() - 17;
          if (value < 1900 || value > adultYear) {
            return false;
          }
          return true;
        }
      )
      .matches(/^[0-9]+$/, 'Must be only digits')
      .min(4, 'Must be 4 digits')
      .max(4, 'Must be 4 digits')
      .required('Valid Year required'),
    dobD: Yup.string()
      .test(
        'dobD',
        'Invalid Day',
        function(day) {
          const month = this.options.parent.dobM;
          const year = this.options.parent.dobY;
          // February
          if (month == 2) {
            const isLeapYear = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);

            if (day > 29 || (day == 29 && !isLeapYear)) {
              return false;
            }
          }
          return true;
        }
      )
      .test(
        'dobD',
        'Invalid Day',
        function(day) {
          const month = this.options.parent.dobM;
          // Check months with less than 31 days
          // 4. April
          // 6. June
          // 9. September
          // 11. November
          if ((month == 4 || month == 6 || month == 9 || month == 11) && day == 31) {
            return false;
          }
          return true;
        }
      )
      .test(
        'dobD',
        'Invalid Day',
        day => {
          if (day < 1 || day > 31) {
            return false;
          }
          return true;
        }
      )
      .matches(/^[0-9]+$/, 'Digits Only')
      .min(2, 'Invalid Day')
      .max(2, 'Invalid Day')
      .required('Required'),  
  }),

旁注:为了可读性,我将每个对 dobD 的检查都移到了它自己的 Yup.test() 中,但这不是必需的。

关于javascript - 使用 Yup.ref 和 .test 根据多个相关字段值验证 Yup 中的字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65135707/

相关文章:

javascript - 关于请求参数的命名/选择的困惑

javascript - Ext JS 类的最佳实践最终会产生过多的 .js 文件。性能怎么样?

javascript - 如何将音频Blob发布到服务器JavaScript和PHP

javascript - jQuery/javaScript 被浏览器忽略( Bootstrap )

css - 在组件内部引用 SCSS 变量

javascript - Flask JSON post 请求不起作用

javascript - 获取reactjs中组件的可选 Prop 列表

c# - Qt 4.7 QRegExp 电子邮件地址验证

java - 在 Spring 中使用验证将 ZonedDateTime 字段限制为毫秒时间的 3 位数字

JQuery 表单验证 - Onblur