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.
Related
I need to show and validate "hourlyCommitment" field ONLY when "commitment" field has a value of "3". The problem is, I can't seem to access the "current index" of the array field, so the validation doesn't work. Any ideas would be appreciated
professionals: Yup.array().of(
Yup.object().shape({
talent: Yup.number().required(translates.FormsErrorsRequired),
seniority: Yup.number().required(translates.FormsErrorsRequired),
commitment: Yup.number().required(translates.FormsErrorsRequired),
hourlyCommitment: Yup.number()
.nullable()
.when('professionals[currentIndex].commitment', {
is: '3',
then: Yup.number().required(translates.FormsErrorsRequired),
}),
quantity: Yup.number().required(translates.FormsErrorsRequired),
skills: Yup.array().of(
Yup.object().shape({
value: Yup.string(),
label: Yup.string(),
})
),
})
),
Seems I solved it:
professionals: Yup.array().of(
Yup.object().shape({
talent: Yup.number().required(translates.FormsErrorsRequired),
seniority: Yup.number().required(translates.FormsErrorsRequired),
commitment: Yup.number().required(translates.FormsErrorsRequired),
hourlyCommitment: Yup.number().test({
name: 'hourlyCommitment',
exclusive: true,
message: translates.FormsErrorsRequired,
test: (value, context) => {
return !!value || context.parent.commitment !== 3;
},
}),
quantity: Yup.number().required(translates.FormsErrorsRequired),
skills: Yup.array().of(
Yup.object().shape({
value: Yup.string(),
label: Yup.string(),
})
),
})
),
Why don't you just use commitment in initial values?
Are they different values with professionals[current].commitment?
If yes, then define a variable called currentCommitment and set it to professionals[current].commitment, then use it in validation
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.
I have been having some problems with react-hook-form and disappearing defaultValues
So I initiate the useForm with default values, and then get async user location from our API. I want to pre-fill the country based on our user data.
unfortunatelly, after I do that, loose all default values inside payment prop.
why is that happening and how can I fix it?
I tried to find some solutions but none seem to help me (setTimeout, useMemo on defaultValues etc)
const form = useForm<CheckoutFormSteps>({
defaultValues: {
team: {
id: null,
icon: 'url',
name: 'someName',
},
payment: {
address1: '',
address2: '',
city: '',
companyName: '',
paymentMethod: PaymentMethod.CreditCard,
country: '',
firstName: '',
lastName: '',
phone: '',
postalCode: '',
state: '',
vat_number: '',
},
},
});
useEffect(() => {
// some async logic to get user's country
form.setValue('payment.country', 'US');
// also tried setTimeout(() => form.setValue('payment.country', 'AU'));
}, []);
then the getValues look like
{
team: {
id: null,
icon: 'url',
name: 'someName',
},
payment: {
country: 'US',
} // all other payment props are gone
}
Here you go with a solution
const form = useForm<CheckoutFormSteps>({
defaultValues: {
team: {
id: null,
icon: 'url',
name: 'someName',
},
payment: {
address1: '',
address2: '',
city: '',
companyName: '',
paymentMethod: PaymentMethod.CreditCard,
country: '',
firstName: '',
lastName: '',
phone: '',
postalCode: '',
state: '',
vat_number: '',
},
},
});
useEffect(() => {
// some async logic to get user's country
form.setValue({
...form,
payment: {
...form.payment,
country: "US"
}
});
// also tried setTimeout(() => form.setValue('payment.country', 'AU'));
}, []);
Whenever you are setting the value, you need to retain the old value as value. For the same reason please use spread operator.
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.
}
}
]
};
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.