Set Yup validation for attribute of Yup array of objects - arrays

I want to set validation for number attribute in Yup array of objects, such that
weight of each object must be >=0 and <=100 in array.
Sum of weights of all objects in array also must be less than 100.
const ParamValidator = Yup.object()
.shape({
params: Yup.array()
.of(
Yup.object()
.shape({
name: Yup.string.max(30).required(),
weight: Yup.number().min(0).max(100).required(),
})
.required(),
)
.required()
However I figured out, I can make point (1.) with min & max for individual object's weight, but not able to do (2.) that how can I put and check sum of all object's weight.
Only use Yup Validation

const ParamValidator = Yup.object()
.shape({
params: Yup.array()
.of(
Yup.object()
.shape({
name: Yup.string.max(30).required(),
weight: Yup.number().min(0).max(100).required(),
})
.required(),
)
.required()
.test('params',
'sum of weights of all objects of params should be <= 100',
(values: any[]) => values.reduce((acc, curr) => acc + curr.weight, 0) <= 100,)

Related

conditionally required field if another field has a value using array of objects

I want to make one field required, but only if the first field has some value on it.
I know I could do something like this, using when if this wasn't an array of objects, but since it is, the validation is not working.
myFieldArray: yup.array().of(
yup.object().shape({
firstField: yup.string(),
secondField: yup.string().when("firstField", {
is: (firstField) => firstField.length > 0,
then: yup.string().required("this field is required"),
}),
})
)
I tried to use yup.ref too, but "when" don't accept refs, only strings
myFieldArray: yup.array().of(
yup.object().shape({
firstField: yup.string(),
secondField: yup.string().when(yup.ref("firstField"), {
is: (firstField) => firstField.length > 0,
then: yup.string().required("this field is required"),
}),
})
)
This one worked
myArray: Yup.array().of(
Yup.object().shape({
firstField: Yup.string(),
secondField: Yup.string().when("firstField", {
is: firstField => firstField && firstField.length > 0,
then: Yup.string().required("this field is required")
})
})
)
Code sandbox => https://codesandbox.io/s/react-formik-yup-forked-wcfkh?file=/src/App.js

Using when validation yup on formik form

Hey guy i have a problem with 2 form input number, min and max, i want the value of max alway greater than min value, if not, using yup to show error, but seem it doesnt work, here is my code. Thank for your help!!
const formikAddFilter = useFormik({
enableReinitialize: true,
initialValues: {
filterName: '',
min: 0,
max: 0,
unValidRange: max > min
},
validationSchema: Yup.object().shape({
unValidRange:Yup.boolean(),
filterName: Yup.string().required('Skill is required'),
max:Yup.number().when('unValidRange',{
is:true,
then: Yup.number().required('max cant less than min')
})
}),
onSubmit: values => {
alert(JSON.stringify(values))
setFilterItem([...filterItem, values])
formikAddFilter.setFieldValue('filterName', '')
formikAddFilter.setFieldValue('min', 0)
formikAddFilter.setFieldValue('max', 0)
}
});
Try this
const validationRange = yup.object().shape({
min: yup.number().required(),
max: yup
.number()
.required()
.test('superior', 'min must be smaller than max', function(f) {
const ref = yup.ref('min');
return f > this.resolve(ref);
})
});
Demo: Stackblitz

Cyclic dependency, node was:"password" in yup

I got the above error. Don't know what happened to the object. My object below.
export const loginValidator = yup.object({
login: yup.string().when('password', {
is: (v) => v < 9999 && v > 999,
then: yup.string().required('Phone No is required').matches(phoneRegExp, 'Must be 10 digits'),
otherwise: yup.string().email().required('Email is required'),
}),
password: yup.string().when('login', {
is: (m) => phoneRegExp.test(m),
then: yup
.string()
.required('Pin is Required')
.matches(/^[0-9]+$/, 'Must be only digits')
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits'),
otherwise: yup.string().required('password is required'),
}),
});
Error I got
Error: Cyclic dependency, node was:"password"
whats going wrong with this
Thanks !!
To avoid Cyclic dependency have to add these values to the yup.
[['login', 'password']]
example,
export const loginValidator = yup.object().shape(
{
login: yup.string().when('password', {
is: (v) => v < 100000,
then: yup.string().required('Phone No is required').matches(phoneRegExp, 'Must be 10 digits'),
otherwise: yup.string().email().required('Email is required'),
}),
password: yup.string().when('login', {
is: (m) => phoneRegExp.test(m),
then: yup
.string()
.required('Pin is Required')
.matches(/^[0-9]+$/, 'Must be only digits')
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits'),
otherwise: yup.string().required('password is required'),
}),
},
[['login', 'password']]
);

schedules[0].timings[0].startTime must be a `string` type, but the final value was: `null` - getting this value when field remains empty

const validationSchema = () => {
return Yup.lazy(values => {
return Yup.object().shape({
name: Yup.string().required("This field is required"),
streetAddress: Yup.string().required("This field is required"),
city: Yup.string().required("This field is required"),
state: Yup.string().required("This field is required"),
zipCode: Yup.string().required("This field is required"),
country: Yup.string().required("This field is required"),
phone: Yup.string().required("This field is required"),
// consultingCharge: Yup.string().required("This field is required"),
schedules: Yup.array().of(
Yup.object().shape({
available: Yup.boolean(),
timings: Yup.array().of(
Yup.object().shape({
startTime: Yup
.string()
.when('available', {
is: true,
then: Yup.string().required('Field is required'),
otherwise: Yup.string()
}),
endTime: Yup
.string()
.when('available', {
is: true,
then: Yup.string().required('Field is required'),
otherwise: Yup.string()
})
.test("", "End time must be after Start time" , function(values){
return this.parent.startTime < values;
}),
})
)
})
)
})
})
}
Facing the below error:
schedules[0].timings[0].endTime must be a string type, but the final value was: null. If "null" is intended as an empty value be sure to mark the schema as .nullable()
When leave the field blank for start time and end time.
I'm not sure if this is related to the schema, I can imagine you use it in combination with formik or some other form library? It looks like your state that is getting validated against that schema is providing a null value for the endTime property. Can you verify it's not an issue with the state object itself? Could it be that you have an input field which is empty and the onChange handler is setting the value from the state to null instead of ""? :)

Conditional form validation with Yup

I am beginner in Yup and I need to do some form validation with Yup. Here is an example of my schema :
const MyFormSchema = Yup.object().shape({
contactId: Yup.string().required(),
phoneNumber : Yup.string().phoneNumber().required(),
email: Yup.string().email().required()
});
My form is valid in 2 cases : either the user enters the contactID or he enters the phoneNumber and the email.
I tried to implement this using test function but was unable to do it. Any help would be appreciated.
You can build the same logic for rest 2 fields:
Yup.object().shape({
contactId: Yup.string().when(["phoneNumber", "email"], {
is: (phoneNumber, email) => !phoneNumber || !email,
then: Yup.string().required()
}),
phoneNumber: Yup.string().when("contractId", {
is: contactId => !!contactId,
then: Yup.string().required()
}),
email: Yup.string().when("contractId", {
is: contactId => !!contactId,
then: Yup.string()
.email()
.required()
})
});
To check for email, you can use built in function Yup.email(). For phone you need to build custom validator:
const PHONE_VALIDATOR = /...your RegEx here.../
...
phoneNumber : Yup.string().matches(PHONE_VALIDATOR, 'Phone is not valid').required()

Resources