React Formik checkbox group does not turn into an array of invidual checked or unchecked elements
Solution 1
It's pretty easy to accomplish using the FieldArray
component.
Place your values in an array, something like this:
const tagCollection = [
{ value: "one", label: "One" },
{ value: "two", label: "Two" },
{ value: "three", label: "Three" }
];
And then use the FieldArray
like this:
<FieldArray
name="tags"
render={arrayHelpers => (
<div>
{tagCollection.map(tag => (
<label key={tag.value}>
<input
name="tags"
type="checkbox"
value={tag}
checked={values.tags.includes(tag.value)}
onChange={e => {
if (e.target.checked) {
arrayHelpers.push(tag.value);
} else {
const idx = values.tags.indexOf(tag.value);
arrayHelpers.remove(idx);
}
}}
/>
<span>{tag.label}</span>
</label>
))}
</div>
)}
/>
Update:
You can also do this by writing your own component.
const MyCheckbox = ({ field, form, label, ...rest }) => {
const { name, value: formikValue } = field;
const { setFieldValue } = form;
const handleChange = event => {
const values = formikValue || [];
const index = values.indexOf(rest.value);
if (index === -1) {
values.push(rest.value);
} else {
values.splice(index, 1);
}
setFieldValue(name, values);
};
return (
<label>
<input
type="checkbox"
onChange={handleChange}
checked={formikValue.indexOf(rest.value) !== -1}
{...rest}
/>
<span>{label}</span>
</label>
);
};
// And using it like this:
<Field component={MyCheckbox} name="tags" value="one" label="One" />
<Field component={MyCheckbox} name="tags" value="two" label="Two" />
<Field component={MyCheckbox} name="tags" value="three" label="Three" />
Solution 2
With Formik 2 without any Formik specific components:
import React from "react";
import { useFormik } from "formik";
export default function App() {
return <ProjectsForm></ProjectsForm>;
}
const tags = ["one", "two", "three"];
const ProjectsForm = () => {
const formik = useFormik({
enableReinitialize: true,
initialValues: {
tags: []
},
onSubmit: (values) => {
console.log(values);
}
});
const handleChange = (e) => {
const { checked, name } = e.target;
if (checked) {
formik.setFieldValue("tags", [...formik.values.tags, name]);
} else {
formik.setFieldValue(
"tags",
formik.values.tags.filter((v) => v !== name)
);
}
};
return (
<form onSubmit={formik.handleSubmit}>
{tags.map((tag) => (
<div key={tag}>
<input
id={tag}
type="checkbox"
name={tag}
checked={formik.values.tags.includes(tag)}
onChange={handleChange}
/>
<label htmlFor={tag}>{tag}</label>
</div>
))}
<button type="submit">Submit</button>
</form>
);
};
I started by creating a simple array of tags.
Then I used useFormik
hook to bind the form for an array of checkboxes. Whether a checkbox is checked, depends on whether it's in the tags array.
Hence: formik.values.tags.includes(tag)
I created a custom change handling function to set or remove a tag from Formik values depending on whether a checkbox is checked or not.
niklasbuhl
Updated on June 08, 2022Comments
-
niklasbuhl almost 2 years
I am using Formik to create a form on a website. In this form I have a set of tags which I want to be checkable with individual checkboxes, but keep them in an array
tags
. Formik claims to be able to do so by using the samename
attribute on the Field elements, but I can not get it to work.I am using this code example as an reference.
Here is my code:
import React from "react"; import ReactDOM from "react-dom"; import { Formik, Form, Field } from "formik"; import "./styles.css"; function App() { return ( <div className="App"> <h1>Hello CodeSandbox</h1> <h2>Start editing to see some magic happen!</h2> <ProjectsForm /> </div> ); } const ProjectsForm = props => ( <Formik initialValues={{ search: "", tags: [] }} onSubmit={values => { console.log(values); }} validate={values => { console.log(values); }} validateOnChange={true} > {({ isSubmitting, getFieldProps, handleChange, handleBlur, values }) => ( <Form> <Field type="text" name="search" /> <label> <Field type="checkbox" name="tags" value="one" /> One </label> <label> <Field type="checkbox" name="tags" value="two" /> Two </label> <label> <Field type="checkbox" name="tags" value="three" /> Three </label> </Form> )} </Formik> ); const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);
Also on CodeSandbox
I am expecting to receive thought the
console.log(values)
to display something like:Object {search: "", tags: ['one', 'three']}
or
Object {search: "", tags: ['one': true, 'two': false, 'three': true]}
Hope there is a simple thing I am missing to add the Formik checkbox group functionality, as it claims to be possible.