我正在使用Formik的FieldArray
将对象动态添加到数组中,并在对象push()
被添加到数组中时渲染其他表单元素。
我的架构如下:
const EMAIL_SCHEMA = Yup.object().shape({
address: Yup.string().email().required( 'E-mail address is required.' ),
isPreferredContact: Yup.boolean()
})
const SCHEMA = Yup.object().shape({
emails: Yup.array()
.of( EMAIL_SCHEMA )
.ensure()
.compact( v => !v.address )
.required( 'At least one e-mail address is required.' )
})
对于每个电子邮件输入,都有一个对应的复选框,以指示它是否是首选的联系人电子邮件地址。不需要需要将电子邮件地址标记为首选。
我想做的是验证数组是否包含最多一个对象,其中isPreferredContact
是true
。如果数组中有3个电子邮件对象,并且所有对象的isPreferredContact
为false
,则为有效状态。就是说:
let values = [
{address: '1@email.com', isPreferredContact: false},
{address: '2@email.com', isPreferredContact: false},
{address: '3@email.com', isPreferredContact: false}
] // OK
let values = [
{address: '1@email.com', isPreferredContact: true},
{address: '2@email.com', isPreferredContact: false},
{address: '3@email.com', isPreferredContact: false}
] // OK
let values = [
{address: '1@email.com', isPreferredContact: true},
{address: '2@email.com', isPreferredContact: true},
{address: '3@email.com', isPreferredContact: false}
] // Invalid
我看到了这个答案
Yup: deep validation in array of objects
显示compact()
方法可用于验证至少一个,因为如果从数组中删除“虚假”值后,该数组为空,则很容易将模式密钥视为无效。
但是,对于验证数组最多包含一个具有property = value谓词的对象,我什么也看不到。
有没有办法做到这一点?
答案 0 :(得分:2)
在GitHub上浏览Yup的问题,盯着API文档(addMethod
的文档确实很糟糕),并在Code Sandbox中进行测试后,我发现这可行:
Yup.addMethod(Yup.array, 'atMostOne', function(args) {
const { message, predicate } = args
return this.test('atMostOne', message, function(list) {
// If there are 2+ elements after filtering, we know atMostOne must be false.
return list.filter(predicate).length < 2
})
})
显然,谓词是一个函数,该函数接受数组的元素并对其执行测试,并返回boolean
。
对于标量值数组,这就像el => el === value
一样简单。对于一组对象,它应该是el => el.property === value
或el[property] === value
。
希望这可以帮助其他对此感到好奇的人。