Closed GazzaHazza closed 5 years ago
Both ideas from https://github.com/jquense/yup/issues/79#issuecomment-274174656 worked for me
const inst = yup.object({
location: yup
.object({
state: yup.string(),
county: yup.string()
})
.test(
'is-optional',
'${path}.state or ${path}.county is required',
function({ state, county }) {
return state === '' && county === '' ? false : true
}
)
})
// throws ValidationError: location.state or location.county is required
inst.validate({
location: {
state: '',
county: ''
}
})
// doesn't throw
inst.validate({
location: {
state: 'CA',
county: ''
}
})
or
const inst2 = yup.object().shape(
{
location: yup.object().shape({
state: yup
.string()
.when('county', {
is: '',
then: yup.string().required(),
otherwise: yup.string()
}),
county: yup
.string()
.when('state', {
is: '',
then: yup.string().required(),
otherwise: yup.string()
})
}, ['county', 'state'])
}
)
I needed either county or state to be filled in
Hi, the second solution worked for me. Thank you very much.
I am having this same issue but both of the solutions seems to suggest that the optional fields needs to be present in their own sub-object, location in the above case.
In my case there is one single level object of user data where the fields in question are mixed in with the rest of the users data. Specifically, to register, a user has to specify an entry in one of the two telephone fields. It's actually a little more complicated than that as certain types of users may have to fill in one of three or more fields but the 'two field' case should be general enough.
The proposed solutions appear to only work if I manually munge the data received so that { name: "John Doe", company: "Test Inc", mobile: "012345678", phone: "" } becomes { name: "John Doe", company: "Test Inc", telephone: { mobile: "012345678", phone: "" } } for the purposes of form validation, and then restructured again for submission. Which seems rather clunky and potentially error prone.
There must be a general solution to the 'one of set of fields is required' problem that doesn't require data to be artificially bent?
I think it would be helpfully to post your data you are attempting to validate as well as your current validation schema. What I posted is simply the scenario that I had to deal with so I outlined my solution based on previous issues. I don’t think my solution would work for everyone thus if you would like help please post sample data and schema. :)
Hi, could anyone tell me where is issue, or what is correct approach, when you have scenario with 'all or nothing' is valid? I've tried to mimic @davidchase solution with following code, but witout success :(
Thank you for every help
var schema = yup.object().shape({
address: yup.object().shape({
city: yup
.string()
.when('zip_code', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
})
.when('street', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
}),
zip_code: yup
.string()
.when('city', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
})
.when('street', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
}),
street: yup
.string()
.when('zip_code', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
})
.when('city', {
is: val => val.length > 0,
then: yup.string().required(),
otherwise: yup.string()
}),
}, ['street', 'zip_code', 'city'])
});
schema.isValid({
address: {
street: 'Street Name',
city: 'City Name',
zip_code: '12345'
}
}).then(valid => console.log(valid))
@cenda the second argument to object.shape()
is not an array of conflicting fields. its an array of field pairs. e.g. [['street', 'zip_code'], ['zip_code', 'city']]
you need to make the list exhaustive
umm, sorry, but I'm afraid I don't understand
@jquense Thanks!
@davidchase Thanks a lot!!! This works for me https://github.com/jquense/yup/issues/193#issuecomment-383712114
const CompanyProfileValidationSchema = Yup.object({ locations: Yup.array().of( Yup.object().shape( { addressType: Yup.string().when(["address", "city", "country", "pincode", "state"], { is: (address, city, country, pincode, state) => address || city || country || pincode || state, then: Yup.string().required("Please Add FacilityType") }), country: Yup.string().when(["address", "addressType", "city", "pincode", "state"], { is: (address, addressType, city, pincode, state) => address || addressType || city || pincode || state, then: Yup.string().required("Please Add Country") }), city: Yup.string().when(["address", "addressType", "country", "pincode", "state"], { is: (address, addressType, country, pincode, state) => address || addressType || country||pincode||state, then: Yup.string().required("Please Add City") }), state: Yup.string().when(["address", "addressType", "city", "country", "pincode"], { is: (address, addressType, city, country, pincode) => address || addressType || city || country || pincode, then: Yup.string().required("Please Add State") }), address: Yup.string().when(["addressType", "city", "country", "pincode", "state"], { is: (addressType, city, country, pincode, state) => addressType || city || country || pincode || state, then: Yup.string().required("Please Add Address") }), pincode: Yup.string().when(["address", "addressType", "city", "country", "state"], { is: (address, addressType, city, country, state) => address || addressType || city || country || state, then: Yup.string().required("Please Add Pincode") }) }, [ ["addressType", "country"], ["addressType", "city"], ["addressType", "pincode"], ["addressType", "address"], ["addressType", "state"], ["country", "city"], ["country", "pincode"], ["country", "address"], ["country", "state"], ["address", "city"], ["address", "pincode"], ["address", "state"], ["state", "city"], ["state", "pincode"], ["city", "pincode"] ] ) ) });
it's a right code for cyclic dependency if not than please help how to solve this
I faced same issue. But i had to pass same dependency twice and it worked for me. I am not sure what is the reason for this. Can someone example?
yup.object().shape(
{
building_number: yup.string().when('building_number', {
is: building_name => Boolean(building_name),
then: yup.string().required(),
}),
street: yup.string().required(),
town: yup.string().required(),
county: yup.string().required(),
},
[['building_number', 'building_number']]
);
Hi, I am having a issue with cyclic dependency within a schema. I have looked at this issue, but what was suggested didn't work for me.
This is my schema. Basically i would like either
building_number
orbuilding_name
to be filled.Thanks for your help in advance.