Checkbox Form Validation with Ant Design

I was working on a simple form in React that needed a checkbox before being allowed to submit. You have to accept the terms and conditions or privacy policy. I used the Ant Design for the React components and since I struggled with adding this ‘simple’ condition, I decided to share my solution.

Let’s start by creating a simple form. This form contains one Input field and one checkbox.

import React from 'react';
import {Form, Input, Button, Checkbox} from 'antd';
import "antd/dist/antd.css";

export default function CheckBoxForm() {

    const submit = async () => {
        try {
            const values = await form.validateFields();
            console.log('Success:', values);
        } catch (errorInfo) {
            console.log('Failed:', errorInfo);
        }
    };

    return (
        <Form name="checkbox-validation">
            <Form.Item
                name="name"
                label="Name">
                <Input placeholder="Please input your name"/>
            </Form.Item>
            <Form.Item
                name="checkbox">
                <Checkbox>
                    Please accept the privacy policy
                </Checkbox>
            </Form.Item>
            <Form.Item>
                <Button type="primary" onClick={submit}>
                    Check
                </Button>
            </Form.Item>
        </Form>
    );
};

If we want to require the input field, we can simply add a rule to the Form.Item. The message field contains the message that is shown when the user tries to submit without entering the required field. We can set the field to be required by setting required to true.

import React from 'react';
import {Form, Input, Button, Checkbox} from 'antd';
import "antd/dist/antd.css";

export default function CheckBoxForm() {

    const submit = async () => {
        try {
            const values = await form.validateFields();
            console.log('Success:', values);
        } catch (errorInfo) {
            console.log('Failed:', errorInfo);
        }
    };

    return (
        <Form name="checkbox-validation">
            <Form.Item
                name="name"
                label="Name"
                rules={[{required: true, message: 'Please input your name',},]}>
                <Input placeholder="Please input your name"/>
            </Form.Item>
            <Form.Item
                name="checkbox">
                <Checkbox>
                    Please accept the privacy policy
                </Checkbox>
            </Form.Item>
            <Form.Item>
                <Button type="primary" onClick={submit}>
                    Check
                </Button>
            </Form.Item>
        </Form>
    );
};

Now we are going to add a rule for the checkbox. Unfortunately required does not give the desired outcome. So we are going to write a custom validator. The validator has the following fields as input:(rule: RuleObject, value: any, callback: (error?: string) => void). Now if we want to validate the current value of the checkbox we are going to useState to make sure we can access this field. We are going save the current value of the checkbox in the state and update it when the checkbox is changed.

import React, {useState} from 'react';
import {Form, Input, Button, Checkbox} from 'antd';
import "antd/dist/antd.css";
import {RuleObject} from "rc-field-form/lib/interface";

export default function CheckBoxForm() {
    const [checked, setChecked] = useState(false);

    const onCheckboxChange = async (e: any) => {
        await setChecked(e.target.checked);
    };

    const submit = async () => {
        try {
            const values = await form.validateFields();
            console.log('Success:', values);
        } catch (errorInfo) {
            console.log('Failed:', errorInfo);
        }
    };

    const validation = (rule: RuleObject, value: any, callback: (error?: string) => void) => {
        if(checked) {
            return callback()
        }
        return callback("Please accept the terms and conditions")
    };

    return (
        <Form name="checkbox-validation">
            <Form.Item
                name="name"
                label="Name"
                rules={[{required: true, message: 'Please input your name',},]}>
                <Input placeholder="Please input your name"/>
            </Form.Item>
            <Form.Item
                name="checkbox"
                rules={[{validator: validation}]}>
                <Checkbox checked={checked} onChange={onCheckboxChange}>
                   Please accept the privacy policy
                </Checkbox>
            </Form.Item>
            <Form.Item>
                <Button type="primary" onClick={submit}>
                    Check
                </Button>
            </Form.Item>
        </Form>
    );
};

Finally, we are going to have to change one last thing. If we check the checkbox now, we will see the error message. This is a bit strange, but luckily it can be solved easily. We are going to add a reference to the form. Then we can trigger the form to revalidate the conditions of the form after changing the checkbox.

import React, {useState} from 'react';
import {Form, Input, Button, Checkbox} from 'antd';
import "antd/dist/antd.css";
import {RuleObject} from "rc-field-form/lib/interface";

export default function CheckBoxForm() {
    const [form] = Form.useForm();
    const [checked, setChecked] = useState(false);

    const onCheckboxChange = async (e: any) => {
        await setChecked(e.target.checked);
        form.validateFields(['checkbox']);
    };

    const submit = async () => {
        try {
            const values = await form.validateFields();
            console.log('Success:', values);
        } catch (errorInfo) {
            console.log('Failed:', errorInfo);
        }
    };

    const validation = (rule: RuleObject, value: any, callback: (error?: string) => void) => {
        if(checked) {
            return callback()
        }
        return callback("Please accept the terms and conditions")
    };

    return (
        <Form form={form} name="checkbox-validation">
            <Form.Item
                name="name"
                label="Name"
                rules={[{required: true, message: 'Please input your name',},]}>
                <Input placeholder="Please input your name"/>
            </Form.Item>
            <Form.Item
                name="checkbox"
                rules={[{validator: validation}]}>
                <Checkbox checked={checked} onChange={onCheckboxChange}>
                   Please accept the privacy policy
                </Checkbox>
            </Form.Item>
            <Form.Item>
                <Button type="primary" onClick={submit}>
                    Check
                </Button>
            </Form.Item>
        </Form>
    );
};

This is how I solved this ‘problem’. I am curious if there are any better solutions if there are please let me know.

2 Comments

  1. I am a little late to the party but hope this helps…

    value
    ? Promise.resolve()
    : Promise.reject(
    “please accept our Terms of Services”
    ),
    },
    ]}
    >
    terms of services…..

  2. You should probably avoid using state for setting the checkbox value (excluding validation for brevity)

    Please accept the privacy policy

Leave a Reply