使用 Yup.ref 和 .test 根据多个相关字段值验证 Yup 中的字段
Validate Field in Yup based on multiple related field values with Yup.ref and .test
我在“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() 中,但这不是必需的。
我在“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() 中,但这不是必需的。