Using when validation yup on formik form - reactjs

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

Related

How to use Formik with React-Select with isMulti?

I'm building a system where we can create a project and assign it to several users by filling up a form using Formik, Yup and React-Select.
However, I'm really struggling with passing the array of users when submitting my form using Formik, Formik doesn't receive the data from React-Select.
Here are snippets of the code:
const validationSchema = () => {
return Yup.object().shape({
title: Yup.string().required('A title is required'),
description: Yup.string().required('A description is required'),
assigned: Yup.array().required('At least one assigned user is required'),
});
};
const formik = useFormik({
initialValues: {
title: '',
description: '',
assigned: [],
},
validationSchema,
validateOnBlur: false,
validateOnChange: false,
onSubmit: (data) => {
ProjectService.create(data).then(() => {
navigate('/projects');
window.location.reload();
});
},
});
The component containing the options to select:
Assign to:
<SelectList
name="users"
options={convertToReactSelectObject(users)}
onChange={(assignedUsers) =>
formik.setFieldValue('assigned', assignedUsers.value)
}
value={formik.values.assigned}
/>
{formik.errors.assigned ? formik.errors.assigned : null}
Does someone have an idea of what I should fix to make it work?
Thank you!
My mistake was that I was trying to only pass the "value" field of the array to Formik which doesn't work. So I've passed the whole array of assigned users
<SelectList
options={convertToReactSelectObject(users)}
value={formik.values.assigned}
onChange={(assignedUser) =>
formik.setFieldValue('assigned', assignedUser)
}
/>
Then on the backend, the new project will only take the value field of the assigned users.
// Create a Project
const project = new Project({
title: req.body.title,
description: req.body.description,
assigned: req.body.assigned.map((e) => e.value),
});

Validation 2 fields with yup and formik

This is my default value:
const defaultValues = {
busi_day: [],
busi_start_time: '09:00',
busi_end_time: '17:00',
};
This is my 2 fields:
<FastField type="time" className="start-time" name="busi_start_time" value={values.busi_start_time} />
<FastField type="time" className="start-time" name="busi_end_time" value={values.busi_end_time} />
This is my validatio using Yup:
const validationSchema = Yup.object().shape({
busi_start_time: Yup.string()
.required(),
busi_end_time: Yup.string()
.required(),
});
Now, I want to validate that the busi_end_time must be after the busi_start_time. For example:
{busi_start_time: '09:00' busi_end_time: '17:00'} is valid but {busi_start_time: '14:00' busi_end_time: '08:00'} is not valid. How I can do that?
Use moment.js library and code below:
Yup.object().shape({
busi_start_time: Yup.string().required("Start time cannot be empty"),
busi_end_time: Yup.string()
.required("end time cannot be empty")
.test("is-greater", "End time should be greater", function (value) {
const { busi_start_time} = this.parent;
return moment(value, "HH:mm").isSameOrAfter(moment(busi_start_time, "HH:mm"));
})
});

React form validation with Yup and Formik for nested object is not working properly

I have a form with nested object something like this,
const schema = Yup.object().shape({
// ...
isMultiDestination: Yup.boolean(),
dropOffDestination1: Yup.object().shape({
place_id: Yup.string().when("isMultiDestination", {
is: true,
then: Yup.string().required("Please enter destinaton 1")
})
}),
dropOffDestination2: Yup.object().shape({
place_id: Yup.string().when("isMultiDestination", {
is: true,
then: Yup.string().required("Please enter destinaton 2")
})
})
// ...
});
const detailsForm = useFormik({
validateOnBlur: true,
validateOnChange: true,
initialValues: {
// ...
isMultiDestination: false,
dropOffDestination1: initPlaceObject,
dropOffDestination2: initPlaceObject
// ...
},
validationSchema: schema
});
After toggling the value of isMultiDestination and validating the form, the errors are not updated.
Validation is failing.
try to set validationSchema like this:
validationSchema: yup.object().shape({ yourValidationSchema }),

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

Set Yup validation for attribute of Yup array of objects

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,)

Resources