Reputation: 462
I have 3 fields in a form, the "type" field is select and from that list, some items enable or disable the "out" field, if is enable I need the "out" field to be less than the "in" field and vice-versa, but if the "out" field is disabled I don't need that validation, I was trying something with .when, but is not working, any ideas on how to do this?
const [disableOutCounterField, setDisableOutCounterField] = useState(false);
const schema = yup.object().shape({
type: yup.string().required(requiredMessage),
in: yup
.number(numberMessage)
.required(requiredMessage)
.integer(integerMessage)
.min(1, positiveMessage)
.typeError(numberMessage)
.when("out", {
is: !disableOutCounterField,
then: yup.number().moreThan(yup.ref("out"), moreThanMessage),
message: moreThanMessage,
}),
out: yup
.number(numberMessage)
.integer(integerMessage)
.typeError(numberMessage)
.lessThan(yup.ref("in"), lessThanMessage),
});
Upvotes: 1
Views: 5041
Reputation: 19152
An alternative I found for this is to regenerate the object validationSchema
from inside a useEffect
.
This has the benefit of using useState
without having them mapped to specific form fields ahead of time, such as if you set something conditionally from the database and don't want to set it as a hidden field somewhere.
const validationPiece = yup.object({
amount: yup
.number()
.typeError('Please enter an amount')
.required('Please enter an amount')
});
const [validationSchema, setValidaitonSchema] = useState(yup.object({}));
const {
register,
handleSubmit,
reset,
formState: { errors },
} = useForm({
resolver: yupResolver(validationSchema),
});
useEffect(() => {
if (needNewPartOfForm) {
const validationSchemaDict = {};
if (needNewPartOfForm.xyz) {
validationSchemaDict['xyz'] = validationPiece; // does this need a cloneDeep?
}
if (needNewPartOfForm.abc) {
validationSchemaDict['abc'] = validationPiece;
}
setValidaitonSchema(yup.object(validationSchemaDict));
}
}, [clientDocs, clientId, reset, teamId]);
Upvotes: 0
Reputation: 24280
The construct:
.when("out", {
is: !disableOutCounterField,
compares the out
value with !disableOutCounterField
, and if they are equal, the then
rule is applied. But quite likely they are never the same.
The check that is needed here is just the value of !disableOutCounterField
by itself, for any value of out
. This can be done using an expression:
.when("out", {
is: value => !disableOutCounterField,
In words: for every out
value, return !disableOutCounterField
, and if it returns true, apply the then
part.
Upvotes: 2