Search code examples
javascriptreactjsantd

Disable input field based on the value of a dynamically created form field in react


I am creating a functionality using antd and react.js to implement dynamic form fields like below link: https://codesandbox.io/s/853qm4?file=/demo.tsx

Here initially I want the price input field to be disabled and once I select any sight value, price should automatically enabled. I have tried with onchange and useState, but in this case price textbox for all the newly added fields became disabled, and all became enable when I select a value from any one field. Can anyone help me on this?


Solution

  • You can check if a sight is selected for a particular list item then make this input as enabled.

    form.getFieldValue(['sights', field.name, 'sight'])

    Here sights is name of list, field.name is index of list item.

    Complete code

    import React from "react";
    import "./index.css";
    import { MinusCircleOutlined, PlusOutlined } from "@ant-design/icons";
    import { Button, Form, Input, Select, Space } from "antd";
    
    const { Option } = Select;
    
    const areas = [
      { label: "Beijing", value: "Beijing" },
      { label: "Shanghai", value: "Shanghai" }
    ];
    
    const sights = {
      Beijing: ["Tiananmen", "Great Wall"],
      Shanghai: ["Oriental Pearl", "The Bund"]
    };
    
    type SightsKeys = keyof typeof sights;
    
    const App: React.FC = () => {
      const [form] = Form.useForm();
    
      const onFinish = (values: any) => {
        console.log("Received values of form:", values);
      };
    
      const handleChange = () => {
        form.setFieldsValue({ sights: [] });
      };
    
      return (
        <Form
          form={form}
          name="dynamic_form_complex"
          onFinish={onFinish}
          style={{ maxWidth: 600 }}
          autoComplete="off"
        >
          <Form.Item
            name="area"
            label="Area"
            rules={[{ required: true, message: "Missing area" }]}
          >
            <Select options={areas} onChange={handleChange} />
          </Form.Item>
          <Form.List name="sights">
            {(fields, { add, remove }) => (
              <>
                {fields.map((field) => (
                  <Space key={field.key} align="baseline">
                    <Form.Item
                      noStyle
                      shouldUpdate={(prevValues, curValues) =>
                        prevValues.area !== curValues.area ||
                        prevValues.sights !== curValues.sights
                      }
                    >
                      {() => (
                        <Form.Item
                          {...field}
                          label="Sight"
                          name={[field.name, "sight"]}
                          rules={[{ required: true, message: "Missing sight" }]}
                        >
                          <Select
                            disabled={!form.getFieldValue("area")}
                            style={{ width: 130 }}
                          >
                            {(
                              sights[form.getFieldValue("area") as SightsKeys] || []
                            ).map((item) => (
                              <Option key={item} value={item}>
                                {item}
                              </Option>
                            ))}
                          </Select>
                        </Form.Item>
                      )}
                    </Form.Item>
                    <Form.Item
                      noStyle
                      shouldUpdate={(prev, cur) =>
                        prev?.sights[field?.name]?.sight !==
                        cur?.sights[field?.name]?.sight
                      }
                    >
                      {() => {
                        const disabled = !form.getFieldValue([
                          "sights",
                          field.name,
                          "sight"
                        ]);
    
                        return (
                          <Form.Item
                            {...field}
                            label="Price"
                            name={[field.name, "price"]}
                            rules={[{ required: true, message: "Missing price" }]}
                          >
                            <Input disabled={disabled} />
                          </Form.Item>
                        );
                      }}
                    </Form.Item>
    
                    <MinusCircleOutlined onClick={() => remove(field.name)} />
                  </Space>
                ))}
    
                <Form.Item>
                  <Button
                    type="dashed"
                    onClick={() => add()}
                    block
                    icon={<PlusOutlined />}
                  >
                    Add sights
                  </Button>
                </Form.Item>
              </>
            )}
          </Form.List>
          <Form.Item>
            <Button type="primary" htmlType="submit">
              Submit
            </Button>
          </Form.Item>
        </Form>
      );
    };
    
    export default App;
    

    Hope this solves your problem