Closed rosskevin closed 7 years ago
So one part is resolved - I can inject any errors not directly mapped to a react formal field name with the unmapped error display component in another issue.
I'm assuming I need to implement a custom validator on object
which will iterate over the chosen keys, is that the most straight-forward way?
ya probably the best way. tbh tho I usually model the above as: color: string().oneOf(colors)
Got it, thanks.
Is there a better resource for using yup
and checkbox's? Can't seem to find examples/documentation. Thanks!
I am struggling to implement both a checkbox
and select
element at the moment.
@DeBraid
yup.object({
terms: yup
.boolean()
.oneOf([true], 'Must Accept Terms and Conditions'),
});
@rosskevin Can you show me a snipped of your code for the checkbox? I am trying to implement checkbox, having a hard time to setup the YUP schema.
anyone know how i can use yup for multiple checkbox?
@lvdang I mentioned in the other issue you can use the react-widgets Selectlist and map your checkbox to an array. Otherwise how you model the schema is up to you, you can use a bunch of boolean fields, an array of values, whatever. The issue you are running into is that there is no "default" input for a group of checkboxes. What you use completely depends on what type of data you are representing as a group of checkboxes
@jquense thanks for the input. I guess I am trying to figure out how yup works with react-formal and selectlist with error detection. How would I declare my yup schemas to map to selectlist for error detection? I guess that is my confusion.
Please, could someone share snippet how to validate that at least one checkbox is checked for the object? I have three different checkboxes with their own names (that's data model of the API) so the color: string().oneOf(colors)
isn't work for me.
@berdyshev Something like this worked for me:
const schema = yup
.object({
red: yup.boolean(),
orange: yup.boolean(),
green: yup.boolean()
})
.test(
'myCustomTest',
null,
(obj) => {
if ( obj.red || obj.orange || obj.green ) {
return true; // everything is fine
}
return new yup.ValidationError(
'Please check one checkbox',
null,
'myCustomFieldName'
);
}
);
@sbreiler I'm trying to figure out how to use your example, but also have a field that isn't a checkbox (e.g. an email address, so at least 1 checkbox has to be checked and the email input should be validated). Any idea of how to make it work? 🙂
@AElmoznino something like this?
let schema = yup
.object()
.shape({
// our "basic" requirements
emailAddress: yup.string().required().email(), // email will be validated by yup (required)
red: yup.boolean(),
orange: yup.boolean(),
green: yup.boolean()
})
;
// extended validation
schema = schema.test( // this test is added additional to any other (build-in) tests
'myCustomCheckboxTest',
null, // we'll return error message ourself if needed
(obj) => {
// only testing the checkboxes here
if ( obj.red || obj.orange || obj.green ) {
return true; // everything is fine
}
return new yup.ValidationError(
'❗ Check at least one checkbox',
null,
'myCustomFieldName'
);
}
);
Hello, can you help me. I don't understand examples above. I have multiple checkbox inputs, user must select at least one (their choice is what to select) How to display error if they try to submit form without selecting checkbox? I don' know how to check if all fields is empty or valid :(
const ValidateCheckBoxSchema = Yup.object().shape({
eventOrganizer: Yup.bool().oneOf([true], "Must agree to something"),
venue: Yup.bool().oneOf([true], "Must agree to something"),
})
....
<Formik initialValues={{
eventOrganizer: false,
venue: false
}}
<Field
type="checkbox"
name="venue"
component={CheckBox}
/>
....
...
If you want to check either one or the other is checked, you should use radio-input.
If you, on the other hand, need to check at least one checkbox is ticked (but could be more than one!), you have to write youre own custom rule for it afaik.
In shape definition only write checkbox as booleans, nothing else:
let ValidateCheckBoxSchema = Yup.object().shape({
eventOrganizer: Yup.bool(),
venue: Yup.bool()
});
Extend your ValidateCheckBoxSchema
like that (maybe don't use const for it):
// extended validation
ValidateCheckBoxSchema = ValidateCheckBoxSchema.test( // this test is added additional to any other (build-in) tests
'myCustomCheckboxTest',
null, // we'll return error message ourself if needed
(obj) => {
// only testing the checkboxes here
if ( obj.eventOrganizer || obj.venue ) { // put every checkbox here
return true; // everything is fine
}
return new yup.ValidationError(
'Must agree to something', // your custom error message
null,
'myCustomFieldName'
);
}
);
But don't quote me on that.
Thank you @sbreiler, it works! :) We need to use let. For radio-input is it the same procedure?
Radio is much simpler, say you have three radio's like that:
<input type="radio" name="myradio" value="green" />
<input type="radio" name="myradio" value="red" />
<input type="radio" name="myradio" value="blue" />
You validate them like:
Yup.object().shape({
myradio: Yup.string().oneOf(["green","red","blue"]).required()
});
Thanks again, @sbreiler, you helped me a lot! :)
can someone help me im using typescript and im getting this error
FirstTaxBox: "FirstTaxBox must be a boolean
type, but the final value was: "on"
."
const handleSubmit = useCallback(async (data: object) => {
try {
const schema = Yup.object({
terms: Yup.boolean().oneOf([true], 'At least one check box should be checked'),
}).shape({
InvestedVal: Yup.string().required('Should be a value'),
FirstTaxBox: Yup.boolean(),
SecondTaxBox: Yup.boolean(),
ThirdTaxBox: Yup.boolean(),
FourthTaxBox: Yup.boolean(),
});
await schema.validate(data, {
abortEarly: false,
});
} catch (err) {
const errors = getValidationErrors(err);
formRef.current?.setErrors(errors);
console.log(errors);
}
}, []);
Hi @jquense, One Question - I am using yup with react-hook-form and I need at least 3 checkboxes to be selected from n number of checkboxes that are created dynamically via an API response. Could you please tell me how to do validation for this?
If we handle checkbox inputs as string array elements my_field: string[]
then
yup.object().shape({
my_field: yup.array().min(1, "at least one must be selected"),
});
This works for me
must select all:
agreementOptions: yup.object({
agreement1: yup.boolean(),
agreement2: yup.boolean(),
agreement3: yup.boolean(),
agreement4: yup.boolean(),
})
.test(
'OK',
'Please comfirm all of above',
a => (a.agreement1 && a.agreement2 && a.agreement3 && a.agreement4) as boolean
)
must select at least one of them:
languages: yup.object({
english: yup.boolean(),
french: yup.boolean(),
tagalog: yup.boolean(),
portuguese: yup.boolean(),
spanish: yup.boolean(),
chinese: yup.boolean(),
other: yup.boolean(),
})
.test(
'OK',
'Please select at least one language.',
lan => (lan.english||lan.french||lan.tagalog||lan.portuguese||lan.spanish||lan.chinese||lan.other) as boolean
)
How are you able to handle ValidationError
? It works well in Fields with formik-material-ui TextField, but is there a way to make it work to a div or label using formik-material-ui? I want to do it in a checkbox question.
My solution:
initialValues
initialValues={{
title: "",
description: "",
entity: "",
categories: [],
}}
Yup object:
categories: Yup.array().test({
name: "categories_test",
exclusive: true,
message: "At least select one",
test: (value) => value.length > 0,
})
Fields
<div>
<Field type="checkbox" name="categories" value="dogs" />
<Field type="checkbox" name="categories" value="cats" />
<Field type="checkbox" name="categories" value="rabbits" />
</div>
Hi, I'm using React Native and I've got the following data structure:
const initialValues = {
exercises: [
{
title: "",
exerciseType: {
reps: false,
duration: false,
extraWeight: false,
},
},
],
};
And this is my exercise Schema
const exerciseSchema = yup.object().shape({
exercises: yup.array().of(
yup.object().shape({
title: yup.string().required().min(2).label("Exercise Name"),
exerciseType: yup.object({
reps: yup.boolean(),
duration: yup.boolean(),
}),
})
),
});
Whilst it's working for title, I can't get it working for the checkboxes. I'm getting the values for reps and duration, but how can I check that at least one of them is true?
yup.object({ terms: yup .boolean() .oneOf([true], 'Must Accept Terms and Conditions'), });
anyone know how i can use yup for multiple checkbox?
Try below validationSchema
const validationSchema = Yup.object({ checked: Yup.array().min(1, 'Select atleast one option of your interest') });
in FormIk use initialValues like below:
<Formik initialValues={{ checked: [] }} />
Understand that the following will return true or false for checkbox on console:
yup.object({ terms: yup .boolean() .oneOf([true], 'Must Accept Terms and Conditions'), });
How can I redefine in the schema to change the output on console to '1' if checked or '0' if unchecked for the checkbox. Thanks!
If we handle checkbox inputs as string array elements
my_field: string[]
thenyup.object().shape({ my_field: yup.array().min(1, "at least one must be selected"), });
only when you give empty array in initial value, Ex, my_field:[]
const checkboxOptions = [
{ key: 'Option 1', value: 'cOption1' },
{ key: 'Option 2', value: 'cOption2' },
{ key: 'Option 3', value: 'cOption3' }
]
const validationSchema = Yup.object({
checkboxOption: Yup.array().min(1, 'Required'),
})
<Formik initialValues={initialValues} validationSchema={validationSchema} onSubmit={onSubmit}>
<FormController
control='checkbox'
label='Checkbox topics'
name='checkboxOption'
options={checkboxOptions} />
</Formik>
Must select at least one if not show error ('Required')
Hello, here have two easy ways to do that:
// In this way, you don't need to specific each checkbox, because you are using .mixed().
const yourYupSchema = yup.object().shape({
yourObject: yup
.mixed()
.label("Object of Booleans")
.test("at-least-one-true", 'At least one selected', (obj) => {
return Object.values(obj).some((value) => value);
}),
});
// or
// In this way, you need to specific each checkbox, this looks more secure in a form validation.
const yourYupSchema = yup.object().shape({
yourObject: yup
.object({
termsAccept: yup.boolean(),
cookieAccept: yup.boolean()
})
.label("Object of Booleans")
.test("at-least-one-true", 'At least one selected', (obj) => {
return Object.values(obj).some((value) => value);
}),
});
this worked for me, i was validating each of these only if the other one did not have an input
step5ValidationSchema: {
//multiple checkboxes, multi select
statement: Yup.array().when("plan", {
is: (plan) => {
return plan === undefined;
},
then: (schema) => schema.min(1, "This field is required"),
otherwise: (schema) => schema.notRequired().optional().nullable(),
}),
//multiple radio buttons, single select
plan: Yup.string().when("statement", {
is: (statement) => {
return statement.length === 0;
},
then: (schema) => schema.required("This field is required"),
otherwise: (schema) => schema.notRequired().optional().nullable(),
}),
},
How can i do this with multiple check boxes? I want to require both to be ticked, then validate the form. Right now if i tick one then it works. But i need to tick both. Also - not using Yup. Thank you.
Using yup + react-hook-form validation what worked for me was this:
const schema = yup
.object({
field: yup
.array()
.of(yup.boolean().nullable()) // Allow boolean or undefined
.test(
"at-least-one-checked",
"Must select at least one option",
(value) => !!value?.some((v) => v === true) // Validate if at least one is true
)
.required(),
})
.required();
const {
control,
handleSubmit,
formState: { errors },
} = useForm({
resolver: yupResolver(schema),
mode: "onChange",
reValidateMode: "onChange",
defaultValues: {
field: options.map((option) => props.field.has(option.id)),
},
});
<Controller
name={`field.${id}`}
control={control}
render={({ field: { onChange, ...field } }) => (
<Checkbox
{...field}
checked={props.field.has(field.id)}
onChange={(event, values) => {
onChange(values);
handleChange(event);
}}
value={id}
/>
)}
/>
Implementing react-formal-material-ui, and trying to figure out how to require at least one of the options is chosen. How would you go about doing this? If it is custom/external, how to inject the validation error back into the react-formal form?