Yup How to get the value of field using .when on the same field? - javascript

How to get the value of field when using when on the same field ?
email: yup
.string()
.when([], {
is: (val: string) => {
console.log('val = ', val)
return true
},
then: (schema) => {
console.log('schema = ', schema)
return schema
},
})
})

I am assuming you want to get the value of email in when condition at is location as well as at then location. then you have wrote everything correctly. just remove starting [] empty array in when condition. It you don't provide any array or string then value of current item will get at is location.
ref: React-hook-form validation when input is empty. Conflict with Yup.matches
I have updated the below as per your latest comment. I have tested this in my JavaScript file. so you might need to convert it as per TSX syntax.
email: yup
.string()
.when({
is: (val) => {
console.log('val = ', val)
return true
},
then: yup.string()
.test('testKey', 'error', (value) => console.log('value at then', value)),
})
})

Related

Why yup is trigger my tests even though previous tests are failing?

I want to validate my object with the schema using yup.
But I notice that when I wrote my own test function it's trigger anyway.
I mean I validate the age property for number, null, positive, integer value. then I want to continue with my own logic test.
So I expect to NOT enter the function unless the previous tests are valid.
I'm not sure if this is how it meant to be, but in this way I must also check for valid input in my tests function, even though I add the number, null, positive, integer checks.
So am I using the yup wrong?
What I expect form yup is not invoke the test if the previous tests are invalid.
stackblitz
import { object, string, number, date, InferType } from 'yup';
let userSchema = object({
age: number()
.nullable()
.positive()
.integer()
.test({
message: 'test message',
test: (v) => {
console.log('in test!', v);
return !!v.toPrecision();
},
}),
});
userSchema
.validate({ age: null })
.then((res) => {
console.log({ res });
})
.catch((e) => {
console.log({ e });
});

How to validate interdependent strings using yup in react native

I have two strings of date start_date and end_date. Below have empty string as there initial value:
export interface FilterSchema {
start_date?: any;
end_date?: any;
}
const initialValues: FilterSchema = {
start_date: '',
end_date: '',
};
Initially they both are empty. But if one of them is selected, then other also needs to be selected. If none of them is selected then there is no need of validation. So I used yup for this in following way:
const filterSchema = yup.object().shape({
start_date: yup.string().when('end_date', {
is: value => value && value != '',
then: yup.string().required('Required'),
}),
end_date: yup.string().when('start_date', {
is: value => value && value != '',
then: yup.string().required('Required'),
}),
});
But I am getting error message:
Cyclic dependency, node was: "end_date"
I am using filterSchema in Formik:
<Formik
onSubmit={facilityFilter}
validationSchema={filterSchema}
....
Fields that depend on another field need to be constructed in the right order, i.e. If endDate depends on startDate then startDate needs to go first, however in your case you want to validate after everything is constructed. Yup isn't able to figure this out so it throws the cyclic dependency error.
If you want to tell Yup to ignore the ordering you can add an array of field pairs to the second argument in the shape method
const filterSchema = yup.object().shape({
start_date: yup.string().when('end_date', {
is: value => value && value != '',
then: yup.string().required('Required'),
}),
end_date: yup.string().when('start_date', {
is: value => value && value != '',
then: yup.string().required('Required'),
}),
}, [["start_date", "end_date"]]);
It's not the best solution for dealing with cyclical dependencies as noted here by the creator of yup: https://github.com/jquense/yup/issues/720

Get the value of another field for validation in Yup Schema

I am using Formik with Yup for validation and TypeScript
I have a field that needs to validate based on the value of another field.
The first field is called price and the second field is called tips. The max tip value is 10% of the what ever the price entered is.
I tried to create validation for this using the following:
tips: yup.number()
.min(0, `Minimum tip is $0`)
.max( parseFloat(yup.ref('price'))* 0.1, "Maximum tip is 10% of the price.");
however this doesn't compile because yup.ref returns a Ref. How can I get the value of the price field in this validation?
number.max cannot reference other field and calculate with it at validation.
If you want to do this, you need to implement own schema with mixed.test.
Here is a example.
tips: number()
.min(0, `Minimum tip is $0`)
.test({
name: 'max',
exclusive: false,
params: { },
message: '${path} must be less than 10% of the price',
test: function (value) {
// You can access the price field with `this.parent`.
return value <= parseFloat(this.parent.price * 0.1)
},
}),
Here is doc.
You can check and try how it works here.
I hope this will help you.
if you don't want to use this.parent to access the other properties values you can use the context.
tips: number()
.min(0, `Minimum tip is $0`)
.test(
'max',
'${path} must be less than 10% of the price',
(value, context) => value <= parseFloat(context.parent.price * 0.1),
),
// OR
tips: number()
.min(0, `Minimum tip is $0`)
.test({
name: 'max',
exclusive: false,
params: { },
message: '${path} must be less than 10% of the price',
test: (value, context) => value <= parseFloat(context.parent.price * 0.1),
}),
For referencing other field value we can use this.parent or ctx.parent in case if our value is not nested.
object({
title: string(),
price: string().test('test-name', 'test-message', (value, ctx) => {
let title = ctx.parent.title;
}),
foo: string()
.test('test-name1', 'test-message1', function (value) {
let title = this.parent.title
})
})
but if we have nested value parent is going to give parent of nested
value. in this case parent is not going to work if we want to access
very parent value. we can access parent value with ctx.from. ctx.from contains parents from bottom to top. for example:
object({
title: string(),
ourObject: object({
param1: string(),
param2: string()
.test('test-name', 'test-msg', (value, ctx) => {
let title = ctx.from[ctx.from.length - 1].value.title
})
})
})
or we can easily access any data we want with providing context to schema when validating
object({
price: string(),
foo: string()
.test('test-name', 'test-message', (value, ctx) => {
let arr = ctx.context.arr;
})
})
.validate({ price: 5, foo: 'boo' }, { context: { arr: [1, 2] } })
.then(() => ...)
.catch((err) => ...)
doc
LIKE SO
.test((val,obj)=>{
console.log(val,obj.parent.otherField)
})
val=>current field value
obj=>object of the whole schema
EXAMPLE::::
date: yup.
string()
.required()
.test('type', 'Date should be future date', (val) => {
console.log(val);
}),
time: yup
.string()
.required()
.test('type', 'Time should be future time', (val,obj) => {
console.log(val,'in time val',obj.parent.date,'date')
}),

How to stop yup validation on disabled fields?

I have the following:
two fields: department and clinic
two radio buttons department and clinic
If the clinic radio button is checked, then the department is disabled.
Now I want yup to validate the clinic field only when it is enabled. I tried something like this
// Clinic:
Yup.string().when('isDisabled', {
is: false,
then: Yup.string.required('clinic required')
})
set tree fields for example department , clinic and kind
the kind field is name for radio buttons and then set value for each radio buttons like department and clinic
and your validation schema is like this:
validationSchema=Yup.object().shape({
kind: Yup.string().required(),
clinic: Yup.string().when("kind", {
is: (val) => val === "clinic",
then: Yup.string().required(‘clinic required’),
otherwise: Yup.string().notRequired()
}),
department: Yup.string().when("kind", {
is: (val) => val === "department",
then: Yup.string().required(‘department required’),
otherwise: Yup.string().notRequired()
}),
})
const object = {
name: 'Foo',
hiddenOnMobileField: 'Boo'
}
// you can use any condition attribute (Ex: isMobile)
export const validationSchema = (isMobile) => yup.object().shape({
name: yup.string().trim().required('name is required'),
// this field disabled on a mobile
hiddenOnMobileField: yup.string()
// use empty array
.when([], {
// any condition to remove validation
is: () => !isMobile,
then: yup.string().trim().required('hiddenOnMobileField is required'),
otherwise: yup.string().notRequired(),
})
})
validationSchema(true).validate(object, { abortEarly: false })
.then(...)
.catch(...)

Conditionally Validation in Yup

How to implement the condition like value of 1 field should always be greater than the value of another field.
here's my schema
value: Yup.number().required(''),
value2: Yup.number().when('value',{
is: (val) => something here
then: Yup.number().required('Required').positive('value should be positive'),
otherwise: Yup.number()
})
I want to check for value2 to always be > value.
How to access value2's value in the when condition?
I'm not sure it's the right way to do it, but I'm using test.
Like this:
yourField: Yup.string().test('should-be-greather-than-yourField2', 'Should be greather than yourfield 2', function(value) {
const otherFieldValue = this.parent.yourField2
if (!otherFieldValue) {
return true;
}
return value > otherFieldValue;
})
Try this if you want to compare more than condition between two fields
import * as Yup from 'yup';
value: Yup.number().required(''),
value2: Yup.number().required()
.moreThan(
Yup.ref('value'),
'Should be more than value2'
)
I'm not sure, but try is: (val) => Yup.number().moreThan(val)
I am validating same fields for email and mobile no so user can validate both is same field.
username: yup
.string().when({
is : value =>isNaN(value),
then: yup.string().required('email/mobileno is required') .matches( Regex.EMAIL_REGX,
'Invalid email',
),
otherwise: yup.string()
.matches(Regex.PHONENO_REGX, StringUtils.phoneNo)
}),

Categories

Resources