Search code examples
javascriptreactjsantd

Update Select Option list based on other Select field selection ant design


<Form
    layout="vertical"
    size="medium"
    className="test-form"
    requiredMark={false}
    onFinish={onFinish}
 >
             <Form.Item
                  name="companyId"
                  label="Company/Customer"
                  rules={[{ required: true, message: "Please select Company!"}]}  
              >
                  <Select
                    onChange={this.handleSelectCompanyOnchange}
                    style={{ width: "50%" }}
                    name="companyId"
                  >
                    {users.map((user, index) => {
                      return (
                        <Option key={index} value={user.companyID}>
                          {user.companyName}
                        </Option>
                      );
                    })}
                  </Select>
                </Form.Item>
            
       <Form.Item
             label="Products"
             name="products"
             rules={[{ required: true, message: "Please select Products!"}]}
        >

            <Select mode="multiple" allowClear style={{ width: "70%" }}>
                    {products.map((product, index) => {
                      if (this.state.companyId == product.companyId) {
                        return (
                          <Option key={index} value={product.id}>
                            {product.productName}
                          </Option>
                        );
                      }
                    })}
             </Select>
           </Form.Item>
      </Form>

I am trying to achieve Options in Products Select element changes according to the Company Select onChange selection.

I have specified onChange in Select and calling this.handleSelectCompanyOnchange. In which I get selected companyId.

In this.state.companyId I had set companyId manually which I will remove.

I am really new to ant design and not able to figure out how to update the Products list once Company is selected.

Here, users and products are json as below.

users: 

[{
companyID: 2
companyName: "TEST1"
},{
companyID: 7
companyName: "TEST2"
}]

products:

[{
companyId: 2
id: 1
productName: "TESTProduct1"
},{
companyId: 7
productName: "TESTProduct2"
id: 2
},{
companyId: 7
id: 3
productName: "TESTProduct3"
},{
companyId: 7
id: 4
productName: "TESTProduct4"
}]

However, I have tried getValueFromEvent but not able to achieve this. I am using Ant design Form and Select for this. Also I did referred to https://github.com/ant-design/ant-design/issues/4862 and how to get field value on change for FormItem in antd


Solution

  • Here is what you need to achieve it.

    1. Use onValuesChange prop of the Form. This is the best place to perform setState when it comes to antd Form field changes, not on Select or Input onChange.

       <Form onValuesChange={handleFormValuesChange}>
           ...
       </Form>
      
    2. A form instance (hook). This is optional in your case, but this is useful on setting and getting form values. See more here about it.

       const [form] = Form.useForm();
      
       <Form form={form} onValuesChange={handleFormValuesChange}>
           ...
       </Form>
      

    This is the product options render looks like, a combination of map and filter where selectedCompanyId comes from state. Take note that don't use index as key if the fixed length of the list is unknown, the react will confuse on this and you will get some logical error. Use some unique id.

    <Form.Item label="Products" name="product">
      <Select>
        {products
          .filter((product) => product.companyId === selectedCompanyId)
          .map((product) => (
            <Option key={product.id} value={product.id}>
              {product.productName}
            </Option>
          ))}
      </Select>
    </Form.Item>
    

    And here is the handleFormValuesChange

    const handleFormValuesChange = (changedValues) => {
      const formFieldName = Object.keys(changedValues)[0];
      if (formFieldName === "company") {
        setSelectedCompanyId(changedValues[formFieldName]);  // perform setState here
        form.setFieldsValue({product: undefined}) //reset product selection
      }
    };
    

    Here is the complete working code in react hooks:

    Edit