Formik Yup Validation of array of things - reactjs

Here's the schema for my data. It includes a few top-level properties but also some nested inputs that are part both a collection things, and an object thing2. An example of the input name for the first input of the second item in the things array is: things[0].inputs[1].value. Formik seems to be attaching the values via the names correctly but the validation doesn't seem to work. Any idea where I'm going wrong?
const schema = {
name: "", // string - required
feed_id: "", //string - required
things: [
{
inputs: [
// zero, one, or more of the following
// They all require a value, but it can really be any type,
{
name: "InputName",
value: "StringInput" // String - required
},
{
name: "InputName",
value: true // boolean - required
},
{
name: "InputName",
value: 5 // number - required
}
]
}
],
thingB: {
inputs: [
// zero, one, or more of the following
{
name: "InputName",
value: "StringInput" // String - required
},
{
name: "InputName",
value: true // boolean - required
},
{
name: "InputName",
value: 5 // number - required
}
]
}
};
And here's my attempt at a YUP validation for it
const inputValidationSchema = yup.array().of(
yup.object().shape({
value: yup
.mixed()
.required()
})
);
const validationSchema = yup.object().shape({
name: yup.string().required(),
feed_id: yup.string().required(),
config: yup.object().shape({
things: yup
.array()
.of(yup.object().shape({ inputs: inputValidationSchema })),
thingB: yup.mixed().oneOf([
yup.object().shape({
inputs: inputValidationSchema
}),
null
])
})
});
It doesn't seem to work and properly attach the errors to the form.

Related

yup some validation is not working with react form hook in react

i am trying to include conditions in yup schema but fail with some validation.
const componentSchema = yup.object().shape(
{
type: yup.string().trim().required('Type is required!'),
label: yup.string().trim().required('Label is required!'),
visibilityDependentOn: yup.string(),
visibilityDependentOnWithOption: yup.string().when('visibilityDependentOn', {
is: '',
otherwise: yup.string().trim().required('Option is required'),
}),
options: yup.array().when('type', {
is: (value) => value === 'multiOptions' || value === 'options',
then: yup
.array()
.of(yup.object().shape({ label: yup.string().required(), value: yup.string().required() }).required())
.min(1, 'Atleast one options'),
}),
tableData: yup.array().when('type', {
is: 'tableData',
then: yup
.array()
.of(
yup.object().shape({
columnLabel: yup.string().trim().required('column Label is required!'),
columnType: yup.string().trim().required('column Type is required!'),
})
)
.required(),
}),
},
['type', 'options', 'visibilityDependentOn', 'visibilityDependentOnWithOption', 'tableData']
)
all the validation working fine except:
in options, the of(...) is not working but the min(...) is working fine.
in tableData same thing happens.
yup version
"yup": "0.32.8"

How can I validate my form conditionally with formik, Yup and React

I am working on react form validation with formik and using yup for the validation schema, I have done some logic but the errors are not returning as what I want.
below is my formik initial values
documents: [
{
countryId: 0,
value: "",
expirationDate: "",
typeId: 1,
issueDate: "",
},
{
countryId: 0,
value: "",
expirationDate: "",
typeId: 2,
issueDate: "",
},
{
countryId: 0,
value: "",
expirationDate: "",
typeId: 3,
issueDate: "",
},
This is my validation schema
documents: yup.array().when("disableRequireDocs", {
is: false,
then: yup.array(
yup
.object({
countryId: yup.number(),
value: yup.string(),
expirationDate: yup.string(),
issueDate: yup.string(),
})
.test("", t("vehicles:emptyField"), function () {
return validateAtleastOne(this);
})
),
}),
this is the validation function inside yup
function validateAtleastOne(context: yup.TestContext<any>) {
const { parent } = context;
if (
!parent[2].value ||
!parent[2].countryId ||
!parent[2].expirationDate ||
!parent[2].issueDate
)
return false;
const arrayWithOutLast = parent.filter(
(el: Documents, index: number) => index < 2
);
const filteredArray = arrayWithOutLast.filter(
(e: Documents) =>
!e.value || e.countryId === 0 || !e.expirationDate || !e.issueDate
);
if (filteredArray.length === arrayWithOutLast.length) return false;
return true;
}
The problem is it let the user to fill any one of the first two forms but the error it returns is not what I want I want a separate error for every field. The user have to fill last (its mandatory) and any one of the first two forms

Yup: Array of Object Conditional Validation

I have a data structure like this:
{
isReceivesSalary: true,
boardMembers: [
{
name: 'David',
country: 'USA',
additionalProperty: {
isReceivingSalary: true
}
},
{
name: 'Dave',
country: 'France',
additionalProperty: {
isReceivingSalary: false
}
}
]
}
When isReceivesSalary is checked then at least one of the boardMembers should have
property isReceivingSalary should be checked.
Below is my validation schema which is not working.
const boardMembersValidation ={
isReceivesSalary: yup.boolean().required(),
boardMembers: yup.array(yup.object.shape({
name: yup.string().required(),
country: yup.string().required(),
additionalProperty: yup.object().shape({
isReceivingSalary: yup.boolean()
})
}))
};
Is it possible to validate at least one of the boardMember should be receiving salary when isReceivesSalary is true?
Also add validation message.

Yup validation for object under array

I am using Formik + Yup for form creation with validation. I have following initial value.
const initialValue = {
title: '',
schedules: [
{
maxGame: '',
bookingDuration: [],
reservationSlots: [
{
from: null,
to: null,
increment: '',
pricePerHours: [
{
guest: '',
price: ''
}
],
pricePerGame: [
{
type: 'Child',
price: ''
}
]
}
]
}
]
};
My current yup schema:
const schema = {Yup.object().shape({
title: Yup.string()
.min(2, 'Must be 2 characters or more')
.required('Title is required'),
schedules: Yup.array().of(
Yup.object().shape({
bookingDuration: Yup.array().when('maxGame', {
is: '',
then: Yup.array().min(1, 'Booking Duration is required'),
otherwise: Yup.array()
}),
maxGame: Yup.number().when('bookingDuration', {
is: (bookingDuration) => bookingDuration.length === 0,
then: Yup.number()
.min(1, 'Max Game must be greater than zero')
.required('Max Game is required either fill booking duration'),
otherwise: Yup.number()
}),
reservationSlots: Yup.array().of(
Yup.object().shape({
from: Yup.date().typeError('Invalid Time'),
to: Yup.date().typeError('Invalid Time'),
increment: Yup.string().required('Time Increment is required'),
pricePerGame: Yup.array().of(
Yup.object().shape({
type: Yup.string(),
price: Yup.string()
.when(['type'], {
is: (type) => type,
then: Yup.string().required('Price is required'),
}),
})
),
},
)
},
[['bookingDuration', 'maxGame']])
)
})
}
I want following validation:
Either one of bookingDuration and maxGame is required.
If bookingDuration.length > 0 then price of pricePerHours should be required.
If price of pricePerHours is filled then bookingDuration should be required.
If maxGame !== '' then price of pricePerGame should be required.
If price of pricePerGame is filled then maxGame should be required.
I am able to apply no. 1 validation but for rest unable to apply validation. Can you please help me on this.

Conditional Yup Validation is not working

I have formik form with below initialValues
const initialValues1 = {
people: [
{
id: Math.random(),
email: "",
isNewUser: true,
profile: {
firstName: "",
lastName: "",
}
}
]
};
I want to validate firstName and lastName only when is isNewUser is true by Yup I am trying below but it is not working. How can validate conditionally in Formik Yup
people: Yup.array().of(
Yup.object().shape({
isNewUser: Yup.boolean(),
profile: Yup.object().shape({
firstName: Yup
.string()
.when('isNewUser', {
is: true,
then: Yup.string().required("First name is required")
}),
})
})
)
formatted code in IDE
people: Yup.array().of(
Yup.object({
isNewUser: Yup.boolean(),
profile: Yup.object().when('isNewUser', {
is: true,
then: Yup.object({
firstName: Yup.string().required('First name is required'),
})
})
})
);
isNewUser is sibling of profile attribute, so we can use it in when for defining profile schema not it's child(first_name) schema directly.
you can also specify else part using otherwise key
when({ 'attrbute', is: 'func or value', then: 'schema if is true', otherwise: 'schema if is false'})
As per docs ,
Adjust the schema based on a sibling or sibling children fields. You
can provide an object literal where the key is is value or a matcher
function, then provides the true schema and/or otherwise for the
failure condition.
So move the isNewUser to reflect as sibling. Like this:
const initialValues1 = {
people: [
{
id: Math.random(),
email: "",
//isNewUser: true, // <--------------- remove this
profile: {
firstName: "",
lastName: "",
isNewUser: true // <---------------- here.
}
}
]
};

Resources