I have this basic yup validation schema for my react project.
const DisplayingErrorMessagesSchema = Yup.object().shape({
username: Yup.string()
.min(2, "Too Short!")
.max(50, "Too Long!")
.required("Required"),
email: Yup.string().email("Invalid email").required("Required")
});
For username, it currently validates the required property when the username field is an empty string, but to validate even more with multiple default strings like "none", and "admin". How can I validate these default strings also for the username field?
They have matches() method that does what you are asking:
username: Yup.string()
.matches(/(none|default)/, { message: "Username invalid", excludeEmptyString: true })
.required("Required"),
Related
Hi I am trying to find a way to compare 2 fields and validate only if they are not equal.
This is the only idea I was able to come up with but it doesn't work:
yup
.number()
.required()
.notOneOf(
[FormField.houseHoldMembers as any],
'error message',
),
Shorted:
const schema = yup.object({
field1: yup.number().required(),
field2: yup
.number()
.required()
.notOneOf([yup.ref('field1'), null], 'The two values should not be equal'),
});
You can compare the two values and validate only if they are not equal like this:
const mySchema = yup.object({
text1: yup.number().required(),
text2: yup
.number()
.required()
.when(["text1"], (text1, schema) => {
console.log(schema);
return schema.notOneOf([text1], "the two values should not be equal");
})
});
You can take a look at this sandbox for a live working example of this solution.
I am making a Joi schema to validate the request query, the schema looks like this.
const validateSchema = Joi.object()
.keys({
'size': Joi
.string()
.regex(/^\d+$/)
.optional(),,
'from': Joi
.string()
.regex(/^\d+$/)
.optional(),
'searchparams': Joi
.string()
.optional()
.allow(''),
'active': '' // do this here
});
In the above schema, I want active field can either be a string or a boolean value, how can I apply the Joi schema validation there ?
I want to validate the array on the base of loan register if loan register is true then array should validate else not.
yup.object().shape({
loan_register: yup.boolean(),
loans: yup.array()
.of(
yup.object().shape({
bank_name: yup.string().required(),
bank_reg_no: yup.string().required(),
loan_amount: yup.string().required(),
})
)
})
The reason why of is not an exported member from yup is because yup needs to know the type of data first. You can only use of once you know the type.
For example: array().of(), string().oneOf(), e.t.c
Hence, in your case, you need to provide the data type and it will solve your problem.
const validationSchema = yup.object({
loan_register: yup.boolean(),
loans: yup.array().when('loan_register', {
is: true,
then: yup.array().of(
yup.object({
bank_name: yup.string().required(),
bank_reg_no:yup.string().required(),
loan_amount:yup.string().required(),
}))
})
})
EDIT: 'When loan_register === true, bank_name, bank_reg_no and loan_amount must be strings and required fields.'
You can translate that requirement into code like following (include Yup conditional validation using .when() ):
const validationSchema = yup.object().shape({
loan_register: yup.boolean(),
loans: yup.array()
.when('loan_register', {
is: true,
then: yup.of(
yup.object().shape({
bank_name: yup.string().required(),
bank_reg_no: yup.string().required(),
loan_amount: yup.string().required(),
})
)
})
})
I think you'll want to utilize .when(). This allows exactly what you're looking for by providing conditional validation checks based off other attribute values.
It has a more explicit approach where you'd add
.when('loan_register', {is: true, then: /* yup schema */ })
I believe the change would look like
yup.object().shape({
loan_register: yup.boolean(),
loans: yup.array()
.when('loan_register', {
is: true,
then: yup.of(
yup.object().shape({
bank_name: yup.string().required(),
bank_reg_no: yup.string().required(),
loan_amount: yup.string().required(),
})
)
})
})
Requirements
I have this getValidationSchema` function. My task entails converting the function that calls it to a map of an object.
Something similar to validationSchema[EDIT_INFO] = someSchema, and call that with all my mappings instead of a function.
export const validationSchemas = {
ADD_USER: Yup.object().shape({
username: Yup.string('Provide a username').required('Username is required'),
email: Yup.string().email('Provide a valid email address'),
password: Yup.string('Provide a password').required('Password is required'),
confirmPassword: Yup.string('Provide your password again')
.required('Password confirmation is required')
.oneOf([Yup.ref('password')], 'Passwords do not match'),
group: Yup.string('Please select a group').required('Group is required')
}),
EDIT_INFO: Yup.object().shape({
username: Yup.string('Provide a username').required('Username is required'),
email: Yup.string().email('Provide a valid email address'),
group: Yup.string('Please select a group').required('Group is required')
}),
EDIT_PASSWORD: Yup.object().shape({
password: Yup.string('Provide a password').required('Password is required'),
confirmPassword: Yup.string('Provide your password again')
.required('Password confirmation is required')
.oneOf([Yup.ref('password')], 'Passwords do not match')
})
};
Here is the function I had until now:
const { mode } = this.props;
if (mode === ActionMode.EDIT_INFO) {
return validationSchemas.EDIT_INFO;
}
if (mode === ActionMode.EDIT_PASSWORD) {
return validationSchemas.EDIT_PASSWORD;
}
return validationSchemas.ADD_USER;
};
This is how i call the function until now.
validationSchema={this.getValidationSchemas}
And this is what I have done until now:
const mapValidationSchema: any;
validationSchemas[(validationSchemas.EDIT_PASSWORD, validationSchemas.EDIT_INFO,
validationSchemas.ADD_USER)] = this.mapValidationSchema;
validationSchema = {this.mapValidationSchema}
I clearly am doing something wrong, as I get multiple errors and the form validation isn't working. Note that the form is in React, and TS.
Also, I was asked to do this, but can you explain to me why is this better than a function with an if statement instead? Except looking cleaner I guess I don't see any merit to this.
Here is my validation schema:
const validationSchema = Yup.object().shape({
person: Yup.object().shape({
name: Yup.string().required('Field is required'),
surname: Yup.string().required('Field is required'),
middleName: Yup.string().required('Field is required'),
email: Yup.string()
.email('Wrong e-mail format')
.required('Field is required')
}),
company: Yup.object().shape({
name: Yup.string().required('Field is required'),
address: Yup.string().required('Field is required'),
email: Yup.string()
.email('Wrong e-mail format')
.required('Field is required')
})
});
And also there are two variables in React State: isPerson and isCompany. How to make validation work conditionally, for example if isPerson is true, then person in validationSchema is required to be validated?
Updated ans: 2020.
you can use Yup conditions
const validationSchema = Yup.object().shape({
isCompany: Yup.boolean(),
companyName: Yup.string().when('isCompany', {
is: true,
then: Yup.string().required('Field is required')
}),
companyAddress: Yup.string().when('isCompany', {
is: (isCompany) => true,//just an e.g. you can return a function
then: Yup.string().required('Field is required'),
otherwise: Yup.string()
}),
});
And make sure to update your form accordingly. I hope you get the point...
You can conditionally add to your validation schema just like any other object:
let validationShape = {
company: Yup.object().shape({
name: Yup.string().required('Field is required'),
address: Yup.string().required('Field is required'),
email: Yup.string()
.email('Wrong e-mail format')
.required('Field is required')
})
};
if (this.state.isPerson) {
validationShape.person = Yup.object().shape({
name: Yup.string().required('Field is required'),
surname: Yup.string().required('Field is required'),
middleName: Yup.string().required('Field is required'),
email: Yup.string()
.email('Wrong e-mail format')
.required('Field is required');
}
const validationSchema = Yup.object().shape(validationShape);
Conditional validations with YUP :
All kinds of validation that can be done with when are as follows:
1. Single value, simple condition :
RULE: Only ask for personName when isPerson true.
personName : Yup.string().when('isPerson', {
is: true,
then: Yup.string().required('Field is required'),
otherwise: Yup.string(),
})
2. Single value, complex condition :
RULE: Only ask for personName when company is "IT".
personName : Yup.string().when('company', {
is: (company)=> company==='IT',
then: Yup.string().required('Field is required'),
otherwise: Yup.string(),
})
3. Multi value, complex condition :
RULE: Only ask for personName when company is "IT" and person is valid.
personName : Yup.string().when(['company', 'isPerson'], {
is: (company,isPerson)=> company==='IT'&& isPerson,
then: Yup.string().required('Field is required'),
otherwise: Yup.string(),
})
While the accepted solution works, it had one problem - two of the fields to be validated were common, and had to be duplicated. In my case, I had majority of the fields common with just 2-4 outliers.
So here is another solution:
Define each schema separately - i.e. 3 schemas - commonSchema for the common fields, personSchema for person specfic fields & companySchema for company specific fields.
Merge the schemas based on the state
const validationSchema = isPerson
? commonSchema.concat(personSchema)
: commonSchema.concat(companySchema)
For details on "concat", refer to the yup docs on github.
email: Yup.string()
.when(['showEmail', 'anotherField'], {
is: (showEmail, anotherField) => {
return (showEmail && anotherField);
},
then: Yup.string().required('Must enter email address')
}),
Multiple fields can also be used for validation.