Open apieceofbart opened 4 years ago
I found a workaround which is to create a fake field on the schema and use yups test
method there. You can get access to other fields by using this.parent
inside test
callback.
Here's an example:
https://codesandbox.io/s/formik-example-using-when-test-of-yup-ni2yt
I'm not sure how can it be handled inside formik - it would probably require introducing another property (like customErrors
) for this case.
Just happened to me: I need it to check for a field that is on the root of the object to validate a deeply nested field. While test() returns false on invalid input, no error is displayed :/
I ran into the same issue. I noticed that adding a test
in the root object causes the error to not be thrown by Formik.
Tracking down the source, I noticed that this behaviour is caused by the error path being empty, as stated in this function: https://github.com/jaredpalmer/formik/blob/f117c04738ed218b5eb8916d7189e0849962d50d/packages/formik/src/Formik.tsx#L1061-L1073
According to yup
, the ValidationError
path is empty at root level:
path: a string, indicating where there error was thrown. path is empty at the root level.
At this point I'm not sure whether this is intended or not
Here the same, yup is working fine, it fills the error object after unsuccessful .test() validation but Formik doesn't display it underneath my customField. Someone solved that problem ?
@DeszczMikolaj perhaps my workaround would help you: https://codesandbox.io/s/formik-example-using-when-test-of-yup-ni2yt
I've also encountered this, and can add that this is a degradation from v1.x.x, worked fine there
Apologies for the noise, but I don't want this to be marked stale. This is still an issue in 2.1.4
Having this same issue. Any workarounds yet?
Like @samuelpetroline I've also noticed that the unset path is the problem. I've worked around this by setting a path in the custom test function by explicitly creating an error. Yup docs for custom test functions show how to do it: https://github.com/jquense/yup#mixedtestname-string-message-string--function-test-function-schema
My code now looks like this:
yup
.object()
.shape({
field1: yup.string(),
field2: yup.string(),
})
.test({
name: "atLeastOneRequired",
test: function(values) {
const isValid = ["field1", "field2"].some(field => isNotEmpty(values[field]));
if(isValid) return true;
return this.createError({
path: "field1 | field2",
message: "One field must be set",
})
}
})
Important is to use a non arrow function for test:
to have this
set correctly. For path
any string will do, even with path: ""
Formik will be able to recognize it as a validation error.
p.s. in case you're wondering how to test for the path being set with jest, this is how:
expect(schema.validate(values)).rejects.toMatchObject({
path: expect.stringMatching(/.*/),
});
Important is to use a non arrow function for test: to have this set correctly
Or just pass context as second argument via arrow function and call createError on that. This is more type-safe than an anonymous function
Using version 2.2.9
and also facing this issue 😩
My code looks like:
referralCode: yup.string().test({
name: 'is-valid',
message: 'This is not a valid referral code',
async test(value, ctx) {
console.log(`Validating: ${value}`);
if (!value) return true;
const isValid = await verifyReferralCode(value);
if (isValid) return true;
console.error(`"${value}" is not a valid referral code`);
return ctx.createError({
message: `"${value}" is not a valid referral code`,
});
},
}),
the code runs find, as the console
statements run. but the form is not showing the error message 😕
Update: this custom function helped me resolve this https://github.com/jaredpalmer/formik/pull/2902#issuecomment-922492137
Using default value before chaining test helped me.
yup.mixed().default({}).test(...)
In case you're in my position, your custom test is working but you didn't include a <ErrorMessage />
component in your form.
First, check to make sure your yup test is actually failing or not by sticking this line of code inside your Formik render:
<pre>{JSON.stringify(errors, null, 2)}</pre>
Like so:
<Formik
// ...props
>
{({ values, errors }) => (
<Form>
<pre>{JSON.stringify(errors, null, 2)}</pre>
// ... rest of input fields
</Form>
)}
</Formik>
If your errors are appearing on the screen then you simply need to provide the correct path inside your error message component like this:
<ErrorMessage name="<name of your input field>" >
Hope this helps 👍🏾
I was able to solve it using <ErrorMessage />
from Formik
import { Field, ErrorMessage } from 'formik';
return (
<div className={is_scheduled ? 'block' : 'hidden'}>
<label htmlFor="schedule_date">
Date
</label>
<Field id="schedule_date" name="schedule_date" type="datetime-local" />
<ErrorMessage name="schedule_date" />
</div>
)
Here's the schema
const validationSchema = object({
is_scheduled: boolean().required(),
schedule_date: date().test(
'future',
'must be future date',
(val, ctx) => {
const selectedDate = dayjs(val);
const now = dayjs(new Date());
if (selectedDate.isAfter(now)) {
return true;
}
return ctx.createError({
message: 'must be future date.',
});
}
),
});
Hope this helps
What if i want to do this validation? the createError
is not working whit this path general
.
export const FormSchema = yup
.object()
.shape({
source: yup.string().required(),
featureType: yup.string().required(),
file: yup.mixed().when('source', {
is: 'file',
then: (schema) => schema.required(),
}),
table: yup.object({
data: yup.array().of(
yup.object({
timestamp: yup.date().required(),
mmsi: yup.string(),
ircs: yup.string(),
extMarking: yup.string(),
name: yup.string(),
flag: yup.string(),
type: yup
.string()
.oneOf(TypeSelectOptions.map((opt) => opt.value))
.required(),
latitude: yup.string(),
longitude: yup.string(),
heading: yup.string(),
})
),
}),
externalPositions: yup.object({
active: yup.boolean(),
}),
})
.test({
name: 'maxMmsi',
test: function (form, { createError }) {
if (
form.externalPositions.active &&
_.uniqBy(form.table.data, 'mmsi').length > 2
)
return createError({
path: 'general',
message: 'Importing is limited to a max of 10 distinct vesselss',
})
return true
},
})
🐛 Bug report
Current Behavior
Formik doesn't throw any error when my custom validation fails. You can see that yup validation works fine when triggered manually however formik doesn't show anything in errors object.
Expected behavior
Formik "errors" should be populated with the custom error.
Reproducible example
https://codesandbox.io/s/formik-example-using-when-test-of-yup-47ds6
Your environment