validationSchema={
Yup.object().shape({
emailAddress: Yup.string().email('Please enter a valid email address'),
phoneHome: Yup.number().typeError('Home Phone must be a number'),
phoneMobile: Yup.number().typeError('Mobile Phone must be a number'),
phoneWork: Yup.number().typeError('Work Phone must be a number'),
})
.test(
'at-least-one-contact',
'You must provide at least one contact method',
value => {
const test = !!(value.emailAddress || value.phoneHome || value.phoneMobile || value.phoneWork);
return Yup.ValidationError(['emailAddress', 'phoneHome', 'phoneMobile', 'phoneWork'], 'one is required', '');
}
)
}
Basically I am getting an error on the value => { definition saying
Type 'ValidationError' is not assignable to type 'boolean | Promise<boolean>'.
Is there an easy way to do this so only one field is required?
Tried this aswell but get the cyclic error
Yup.object().shape({
emailAddress: Yup.string()
.email('Please enter a valid email address')
.when(['phoneHome', 'phoneMobile', 'phoneWork'], {
is: (phoneHome, phoneMobile, phoneWork) => !phoneHome && !phoneMobile && !phoneWork,
then: Yup.string().required('Atleast one contact field is required.'),
}),
phoneHome: Yup.number()
.typeError('Please enter a number.')
.when(['emailAddress', 'phoneMobile', 'phoneWork'], {
is: (emailAddress, phoneMobile, phoneWork) => !emailAddress && !phoneMobile && !phoneWork,
then: Yup.number().required('Atleast one contact field is required.'),
}),
phoneMobile: Yup.number()
.typeError('Please enter a number.')
.when(['emailAddress', 'phoneHome', 'phoneWork'], {
is: (phoneHome, emailAddress, phoneWork) => !phoneHome && !emailAddress && !phoneWork,
then: Yup.number().required('Atleast one contact field is required.'),
}),
phoneWork: Yup.number().typeError('Work Phone must be a number')
.typeError('Please enter a number.')
.when(['emailAddress', 'phoneHome', 'phoneMobile'], {
is: (phoneHome, phoneMobile, emailAddress) => !phoneHome && !phoneMobile && !emailAddress,
then: Yup.number().required('Atleast one contact field is required.'),
}),
})
Edit:
In the mean time going to use <Formik /> validate method to just do all my validation. Preferably will get the schema working eventually. But can't be blocked by this work for too long unfortunately. Will be back on it next week. Or if someone manages to sort this out overnight haha
Please see previous issues on deal with cyclic errors thanks!
@pmonty I've made an atLeastOneRequired helper https://runkit.com/anber/yup---at-least-one
I use this:
const Yup = require('yup')
Yup.addMethod(Yup.object, 'atLeastOneOf', function(list) {
return this.test({
name: 'atLeastOneOf',
message: '${path} must have at least one of these keys: ${keys}',
exclusive: true,
params: { keys: list.join(', ') },
test: value => value == null || list.some(f => value[f] != null)
})
})
const Schema = Yup.object()
.shape({
one: Yup.number(),
two: Yup.number(),
three: Yup.number()
})
.atLeastOneOf(['one', 'two'])
Schema.isValidSync({ three: 3 }) // false
Schema.isValidSync({ one: 1, three: 3 }) // true
@calmattack,
I had a similar situation and solved it with the following code.
My solution requires selecting other input elements and checking the value. With more time you could probable adept @risenforces solution to pass in the schema for validation instead of selecting elements.
yup.addMethod(yup.string, 'requiredIf', function(list, message) {
return this.test('requiredIf', message, function(value) {
const { path, createError } = this;
// check if any in list contain value
// true : one or more are contains a value
// false: none contain a value
var anyHasValue = list.some(value => {
// return `true` if value is not empty, return `false` if value is empty
return Boolean(document.querySelector(`input[name="${value}"]`).value);
});
// returns `CreateError` current value is empty and no value is found, returns `false` if current value is not empty and one other field is not empty.
return !value && !anyHasValue
? createError({ path, message })
: true;
});
});
const schema = yup.object().shape({
email: yup.string().requiredIf(['work','home','cell']),
work: yup.string().requiredIf(['email','home','cell']),
home: yup.string().requiredIf(['email','work','cell']),
cell: yup.string().requiredIf(['email','work','home']),
});
I use this:
const Yup = require('yup') Yup.addMethod(Yup.object, 'atLeastOneOf', function(list) { return this.test({ name: 'atLeastOneOf', message: '${path} must have at least one of these keys: ${keys}', exclusive: true, params: { keys: list.join(', ') }, test: value => value == null || list.some(f => value[f] != null) }) }) const Schema = Yup.object() .shape({ one: Yup.number(), two: Yup.number(), three: Yup.number() }) .atLeastOneOf(['one', 'two']) Schema.isValidSync({ three: 3 }) // false Schema.isValidSync({ one: 1, three: 3 }) // true
The check in that test doesn't work well for strings because it allows an empty string. To support strings, you can change it to:
test: value => value == null || list.some(f => !!value[f])
Most helpful comment
I use this: