skip to Main Content

Hello stack overflow community, I’m trying to create a modal form using ant design version 5.3.1. I want my form to have three input components that are always shown and several others that are only shown when you check the checkbox that says "Show Advanced Filters". I’ve implemented it in the following way:

// Some code omitted
const [showAdvancedFilters, setShowAdvancedFilters] = useState(false)

const onChange = (e) => {
  setShowAdvancedFilters(e.target.checked)
}

const [form] = Form.useForm()
return (
      <Modal
        open={open}
        title="Enter Property Details"
        okText="Create"
        cancelText="Cancel"
        onCancel={onCancel}
        onOk={() => {
          form
            .validateFields()
            .then((values) => {
              form.resetFields()
              onCreate(values)
            })
            .catch((info) => {
              console.log('Validate Failed:', info)
            })
        }}
      >
        <Form
         form={form}
         layout="vertical"
         name="form_in_modal"
         initialValues={{
           modifier: 'public'
         }}
       >
          <Form.Item
            name="area"
            label="Search Area"
            // initialValue={'Atlanta Georgia'}
            rules={[
              {
                required: true
              }
            ]}
          >
            <Input placeholder="Input search term"/>
          </Form.Item>
          <Form.Item
            name="mortgage"
            style={{
              marginBottom: 0
            }}
          >
            <Form.Item
              name="downpayment"
              label="Down Payment Percentage"
              rules={[
                {
                  required: true
                }
              ]}
              style={{
                display: 'inline-block',
                width: 'calc(50% - 8px)'
              }}
            >
              <Input placeholder="Input down payment percentage" />
            </Form.Item>
            <Form.Item
              name="interest"
              label="Interest Rate"
              rules={[
                {
                  required: true
                }
              ]}
              style={{
                display: 'inline-block',
                width: 'calc(50% - 8px)',
                margin: '0 8px'
              }}
            >
              <Input placeholder="Input interest rate" />
            </Form.Item>
          </Form.Item>
          <Form.Item name="disabled">
            <Checkbox checked={showAdvancedFilters} onChange={onChange}>Show advanced filters</Checkbox>
          </Form.Item>
          <Form.Item
            name="price"
            style={{
              marginBottom: 0,
              display: showAdvancedFilters ? 'block' : 'none'
            }}
          >
            <Form.Item
              name="minPrice"
              label="Min Price"
              rules={[
                {
                  required: false
                }
              ]}
              style={{
                display: showAdvancedFilters ? 'inline-block' : 'none',
                width: 'calc(50% - 8px)'
              }}
            >
              <Input placeholder="Input min price" />
            </Form.Item>
            <Form.Item
              name="maxPrice"
              label="Max Price"
              rules={[
                {
                  required: false
                }
              ]}
              style={{
                display: showAdvancedFilters ? 'inline-block' : 'none',
                width: 'calc(50% - 8px)',
                margin: '0 8px'
              }}
            >
              <Input placeholder="Input max price" />
            </Form.Item>
          </Form.Item>
          <Form.Item
            name="maxHoa"
            label="Max Hoa"
            rules={[
              {
                required: false
              }
            ]}
            style={{
              display: showAdvancedFilters ? 'block' : 'none'
            }}
          >
            <Input placeholder="Input max hoa" />
          </Form.Item>
          <Form.Item
            name="disabled"
            valuePropName="checked"
            style={{
              display: showAdvancedFilters ? 'block' : 'none'
            }}
          >
              <Checkbox style={{
                display: showAdvancedFilters ? 'inline' : 'none'
              }}>
                Single story only
              </Checkbox>
          </Form.Item>
          <Form.Item
              name="bedrooms"
              style={{
                marginBottom: 0,
                display: showAdvancedFilters ? 'block' : 'none'
              }}
            >
              <Form.Item
                name="minBedrooms"
                label="Min Bedrooms"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)'
                }}
              >
                <Input placeholder="Input min bedrooms" />
              </Form.Item>
              <Form.Item
                name="maxBedrooms"
                label="Max Bedrooms"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)',
                  margin: '0 8px'
                }}
              >
                <Input placeholder="Input max bedrooms" />
              </Form.Item>
          </Form.Item>
          <Form.Item
              name="bathrooms"
              style={{
                marginBottom: 0,
                display: showAdvancedFilters ? 'block' : 'none'
              }}
            >
              <Form.Item
                name="minBathrooms"
                label="Min Bathrooms"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)'
                }}
              >
                <Input placeholder="Input min bathrooms" />
              </Form.Item>
              <Form.Item
                name="maxBathrooms"
                label="Max Bathrooms"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)',
                  margin: '0 8px'
                }}
              >
                <Input placeholder="Input max bathrooms" />
              </Form.Item>
          </Form.Item>
          <Form.Item
              name="yearBuilt"
              style={{
                marginBottom: 0,
                display: showAdvancedFilters ? 'block' : 'none'
              }}
            >
              <Form.Item
                name="minYearBuilt"
                label="Min Year Built"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)'
                }}
              >
                <Input placeholder="Input min year built" />
              </Form.Item>
              <Form.Item
                name="maxYearBuilt"
                label="Max Year Built"
                rules={[
                  {
                    required: false
                  }
                ]}
                style={{
                  display: showAdvancedFilters ? 'inline-block' : 'none',
                  width: 'calc(50% - 8px)',
                  margin: '0 8px'
                }}
              >
                <Input placeholder="Input max year built" />
              </Form.Item>
          </Form.Item>
        </Form>
      </Modal>
    )

Note that I am using showAdvancedFilters to control the display style, which controls whether or not that component appears. Visually this works well, but when you check or uncheck the box, it re-renders the modal and all of the form items inside it, clearing all the previous input. How can I implement this logic without re-rendering everything?

Here are the screenshots showing the modal in checked and unchecked state.

unchecked
checked

Another approach I tried was using {showAdvancedFilters && (rest of my form items)} instead of the display style but this ran into the same issue. Please let me know what you suggest. I couldn’t find any examples of this in their documentation. All help is greatly appreciated, thanks!

2

Answers


  1. Here is an example pulled from the docs at Ant Design for the form component. Try doing something similar to what they did under the getFieldValue function.

    import { Button, Form, Input, Select } from 'antd';
    import React from 'react';
    
    const { Option } = Select;
    
    const layout = {
      labelCol: { span: 8 },
      wrapperCol: { span: 16 },
    };
    
    const tailLayout = {
      wrapperCol: { offset: 8, span: 16 },
    };
    
    const App: React.FC = () => {
      const [form] = Form.useForm();
    
      const onGenderChange = (value: string) => {
        switch (value) {
          case 'male':
            form.setFieldsValue({ note: 'Hi, man!' });
            break;
          case 'female':
            form.setFieldsValue({ note: 'Hi, lady!' });
            break;
          case 'other':
            form.setFieldsValue({ note: 'Hi there!' });
            break;
          default:
        }
      };
    
      const onFinish = (values: any) => {
        console.log(values);
      };
    
      const onReset = () => {
        form.resetFields();
      };
    
      const onFill = () => {
        form.setFieldsValue({ note: 'Hello world!', gender: 'male' });
      };
    
      return (
        <Form
          {...layout}
          form={form}
          name="control-hooks"
          onFinish={onFinish}
          style={{ maxWidth: 600 }}
        >
          <Form.Item name="note" label="Note" rules={[{ required: true }]}>
            <Input />
          </Form.Item>
          <Form.Item name="gender" label="Gender" rules={[{ required: true 
    }]}>
            <Select
              placeholder="Select a option and change input text above"
              onChange={onGenderChange}
              allowClear
            >
              <Option value="male">male</Option>
              <Option value="female">female</Option>
              <Option value="other">other</Option>
            </Select>
          </Form.Item>
          <Form.Item
            noStyle
            shouldUpdate={(prevValues, currentValues) => prevValues.gender 
    !== currentValues.gender}
          >
            {({ getFieldValue }) =>
              getFieldValue('gender') === 'other' ? (
                <Form.Item name="customizeGender" label="Customize Gender" 
    rules={[{ required: true }]}>
                  <Input />
                </Form.Item>
              ) : null
            }
          </Form.Item>
          <Form.Item {...tailLayout}>
            <Button type="primary" htmlType="submit">
              Submit
            </Button>
            <Button htmlType="button" onClick={onReset}>
              Reset
            </Button>
            <Button type="link" htmlType="button" onClick={onFill}>
              Fill form
            </Button>
          </Form.Item>
        </Form>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
  2. Here is a working example. Source from

    const App: React.FC = () => {
      const [value, setValue] = React.useState(false);
    
      const onFinish = (values: any) => {
        console.log('Success:', values);
      };
    
      return (
        <Form
          labelCol={{ span: 8 }}
          wrapperCol={{ span: 16 }}
          initialValues={{ username: "Hans" }}
          onFinish={onFinish}
        >
          <Form.Item
            label="Username"
            name="username"
          >
            <Input />
          </Form.Item>
          <Form.Item>
            <Checkbox onChange={(e) => setValue(e.target.checked)}>Show additional field</Checkbox>
          </Form.Item>
          {value && 
            <Form.Item name="additionalField" label="Additional Field"><Input /></Form.Item>
          }
          <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
            <Button type="primary" htmlType="submit">
              Submit
            </Button>
          </Form.Item>
        </Form>
      );
    };
    
    export default App;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search