I'm using Formik's FieldArray
to add objects dynamically to an array, rendering additional form elements as objects are push()
ed to the array.
My schema looks like this:
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.' )
})
For each e-mail input, there is a corresponding checkbox to indicate if it is the preferred contact e-mail address. No e-mail addresses are required to be marked as preferred.
What I would like to do is validate that the array contains at most one object where isPreferredContact
is true
. If there are 3 e-mail objects in the array and isPreferredContact
is false
for all of them, that's a valid state. That is to say:
let values = [
{address: '[email protected]', isPreferredContact: false},
{address: '[email protected]', isPreferredContact: false},
{address: '[email protected]', isPreferredContact: false}
] // OK
let values = [
{address: '[email protected]', isPreferredContact: true},
{address: '[email protected]', isPreferredContact: false},
{address: '[email protected]', isPreferredContact: false}
] // OK
let values = [
{address: '[email protected]', isPreferredContact: true},
{address: '[email protected]', isPreferredContact: true},
{address: '[email protected]', isPreferredContact: false}
] // Invalid
I see this answer
Yup: deep validation in array of objects
shows that the compact()
method can be used to validate for at least one, because if after removing "falsy" values from the array, the array is empty, then it's easy to treat the schema key as invalid.
There's nothing I can see, though, for validating that the array contains at most one object with a property = value predicate.
Is there a way to do this?