Search code examples
reactjsformsantdant-design-pro

How to disable Antd DatePicker input with Checkbox created with dynamic List


Good afternoon guys!

I have to make a form with dynamics inputs to send a list of experiences of workers. I have trouble with endDate datepicker input, I need to disabled it in case the worker check the checkbox declaring that work experience, is his current job.

I tried to use React states to get the values of the checkbox field but after checking the values of fields, key, name and restField, I got this data:

data form in console

This is my code

import React from "react";
import { Button, Form, DatePicker, Checkbox, Space } from "antd";

const App: React.FC = () => {
  const onFinish = (values: any) => {
    console.log("Received values of form:", values);
  };

  return (
    <Form
      name="dynamic_form_nest_item"
      onFinish={onFinish}
      style={{ maxWidth: 600 }}
      autoComplete="off"
    >
      <Form.List name="experience">
        {(fields, { add, remove }) => (
          <>
            {fields.map(({ key, name, ...restField }) => (
              <Space
                key={key}
                style={{ display: "flex", marginBottom: 8 }}
                align="baseline"
              >
                <Form.Item
                  {...restField}
                  name={[name, "startDate"]}
                  rules={[{ required: true, message: "Missing start date" }]}
                >
                  <DatePicker picker="month" />
                </Form.Item>
                <Form.Item
                  {...restField}
                  name={[name, "endDate"]}
                >
                  <DatePicker placeholder="" picker="month" />
                </Form.Item>
                <Form.Item {...restField} name={[name, "presentJob"]}>
                  <Checkbox />
                </Form.Item>
                <span onClick={() => remove(name)}>Remove field</span>
              </Space>
            ))}
            <Form.Item>
              <Button type="dashed" onClick={() => add()} block>
                Add experience
              </Button>
            </Form.Item>
          </>
        )}
      </Form.List>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

export default App;

This is a link to a codesandbox example: codeSandBox


Solution

  • There are various ways to handle endDate. Since you are using latest version of antd, you can use Form.useWatch hook. You need to pass the complete path and listen for presentJob. When it's true, disabled endDate datepicker.

    Here's the complete code

    import { Button, Form, DatePicker, Checkbox, Space } from "antd";
    
    const EndDate = ({ name }: { name: number }) => {
      const presentJob = Form.useWatch(["experience", name, "presentJob"]);
    
      // It's better to hide this field if presentJob is true
    
      return (
        <Form.Item
          name={[name, "endDate"]}
          rules={[{ required: !presentJob, message: "Missing start date" }]}
        >
          <DatePicker placeholder="End Date" picker="month" disabled={presentJob} />
        </Form.Item>
      );
    };
    
    const App = () => {
      const [form] = Form.useForm();
    
      const onFinish = (values: any) => {
        console.log("Received values of form:", values);
      };
    
      return (
        <Form
          form={form}
          name="dynamic_form_nest_item"
          onFinish={onFinish}
          style={{ maxWidth: 600 }}
          autoComplete="off"
        >
          <Form.List name="experience">
            {(fields, { add, remove }) => (
              <>
                {fields.map(({ key, name, ...restField }) => (
                  <Space
                    key={key}
                    style={{ display: "flex", marginBottom: 8 }}
                    align="baseline"
                  >
                    <Form.Item
                      {...restField}
                      name={[name, "startDate"]}
                      rules={[{ required: true, message: "Missing start date" }]}
                    >
                      <DatePicker placeholder="Start Date" picker="month" />
                    </Form.Item>
                    <EndDate name={name} />
                    <Form.Item
                      {...restField}
                      name={[name, "presentJob"]}
                      valuePropName="checked"
                    >
                      <Checkbox
                        onChange={(e) => {
                          if (e.target.checked) {
                            form.setFieldValue(
                              ["experience", name, "endDate"],
                              undefined
                            );
                          }
                        }}
                      />
                    </Form.Item>
                    <span onClick={() => remove(name)}>Remove field</span>
                  </Space>
                ))}
                <Form.Item>
                  <Button type="dashed" onClick={() => add()} block>
                    Add experience
                  </Button>
                </Form.Item>
              </>
            )}
          </Form.List>
          <Form.Item>
            <Button type="primary" htmlType="submit">
              Submit
            </Button>
          </Form.Item>
        </Form>
      );
    };
    
    export default App;