dawn
dawn

Reputation: 1342

How to make Formik detect when Checkbox field is checked?

I'm making a Checkbox component which needs validation (done with Yup). But it doesn't retrieves the actual value from the checbox, just from the one inside initialValues.

Code of the form:

    <div className='metro custom-pg'>
      <ThemeContext.Provider theme={theme}>
        <Formik
          initialValues={{
            text: '',
            email: '',
            phone: '',
            select: '',
            multi: [],
            checkbox: false,
          }}
          validationSchema={Schema}
          onSubmit={(values) => {
            alert(JSON.stringify(values, null, 2));
            console.log("values", values);
          }}
        >
          {({
            errors,
            values,
            touched,
            handleSubmit,
            setFieldValue,
            setFieldTouched,
          }) => (
            <Form onSubmit={handleSubmit}>
              <Field
                id='text-field'
                label='Plain text'
                name='text'
                type='text'
                placeholder='Enter some characters'
                component={TextField}
              />
              <Field
                id='email-field'
                label='Email'
                name='email'
                type='email'
                placeholder='Enter your email'
                component={TextField}
              />
              <Field
                id='phone-email'
                label='Phone'
                name='phone'
                type='phone'
                placeholder='Enter your phone'
                component={TextField}
              />
              <Field
                id='select'
                name='select'
                name='select'
                label='Select an option'
                options={options}
                component={Select}
              />
              <MultiSelect
                id='multiselect'
                name='multi'
                label='Select multiple options'
                options={multiOptions}
                value={values.multi}
                onChange={setFieldValue}
                onBlur={setFieldTouched}
                touched={touched.multi}
                error={errors.multi}
              />
              <Field
                type="checkbox"
                name='check'
                id='check'
                label='Check the mark'
                component={Checkbox}
              />
              <Button variant="primary" type="submit">Submit</Button>
              </Form>
          )}
        </Formik>
      </ThemeContext.Provider>
    </div>

Code of Checkbox:

// @flow
import * as React from "react";
import { Field, ErrorMessage } from 'formik';
import { FormGroup, FormLabel } from "react-bootstrap";

export type Props = {
  label?: String,
  id?: String,
  name?: String,
  disabled?: boolean,
  onChange: function,
  className?: string
};

export const Checkbox = ({ label, disabled, id, className }: Props) => {
  return (
    <FormGroup>
      <input type="checkbox" id={name} name={name} />
      <label htmlFor={name}> {label}</label>
      <ErrorMessage component="div" className="input-error" name="checkbox" />
    </FormGroup>
  );
};

Checkbox.defaultProps = {
  label: 'Default text',
  name: 'checkbox',
  disabled: false,
  className: ''

}

export default Checkbox;

Upvotes: 7

Views: 25146

Answers (2)

Muni Perez
Muni Perez

Reputation: 90

To complement Adrian Naranjo's answer, you are implementing Formik's "onChange" callback on the checkbox.

<Formik
 initialValues={{ ... }}
 validationSchema={Schema}
 onSubmit={(values) => { ... }}
>
{
  ({ handleChange, ...rest } => {

You need to pass this handleChange to your Checkbox component.

Formik's Field component will make an onChange callback available then you can pass it to the <input type="checkbox" />.

https://jaredpalmer.com/formik/docs/api/field

Upvotes: 3

Adrian
Adrian

Reputation: 945

You assign different name to Checkbox component:

Instead of:

 <Field
   type="checkbox"
   name='check'
   id='check'
   label='Check the mark'
   component={Checkbox}
/>

Use:

 <Field
   type="checkbox"
   name='checkbox'
   id='check'
   label='Check the mark'
   component={Checkbox}
/>

Check if your Checkbox works now.

And don't forget to check if your checkbox is changing value, I think you should implement setFieldValue inside Checkbox component to send new value to formik.

You can access to setFieldValue in Checkbox`s props.

Final code Checkbox will be:

//You need to include form and name in props.
export const Checkbox = ({ form, name, label, disabled, id, className }: Props) => {
  return (
    <FormGroup>
      // You need to include onChange
      <input type="checkbox" id={name} name={name} onChange={(e) => {form.setFieldValue(name,e.target.checked)}}/>
      <label htmlFor={name}> {label}</label>
      <ErrorMessage component="div" className="input-error" name="checkbox" />
    </FormGroup>
  );
};

Upvotes: 4

Related Questions