Archit Sandesara
Archit Sandesara

Reputation: 645

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

Upvotes: 4

Views: 16374

Answers (3)

Awara Amini
Awara Amini

Reputation: 572

Lets say you want to update your option list based on data you get from backend; note:categories is an array object. From this array you take out label and value for each option, see below:

const newOptions = categories.map((item, index) => {
return {
    label: item.name,
    value: item._id,
  };
});

Then use newOptions inside your form like that:

<Form.Item label="anyName" name="anyName">
  <Select style={{ width: 220 }} onChange={ handleChange } options={ newOptions } />
</Form.Item>

Upvotes: 0

Justin Dang
Justin Dang

Reputation: 374

the idea here is that you only need to watch the value change in the state. For example, your select should "watch" a value of state and then you can easily update the state via its own setState method of React. Inside of an onChange event, you can simply just do something with our state.

<Select 
  value={state.productId}
  onChange={e => {// Do something}}
>
 {...} 
<Select/>

Below is my example code how did I update the day every time I reselect week selection. Hopefully that this can help you.

import { Divider, Select } from 'antd';
import React, { useState } from 'react';

export function Example(): JSX.Element {
    const [state, setState] = useState<{week: number, day: number}>({
        day: 1,
        week: 1
    });
    const weeks = [1,2,3,4];
    const days = [1,2,3,4,5];
    return <>
        <Select
            value={state.week}
            onChange={(value) => setState({ week: value, day: 1})}
        >
            {
                weeks.map(week => {
                    return <Select.Option
                        key={week}
                        value={week}
                    >
                        {week}
                    </Select.Option>;
                })
            }
        </Select>

        <Divider/>

        <Select
            value={state.day}
            onChange={(value) => setState({...state, day: value})}
        >
            {
                days.map(day => {
                    return <Select.Option
                        key={day}
                        value={day}
                    >
                        {day}
                    </Select.Option>;
                })
            }
        </Select>
    </>;
}

Upvotes: 0

Chanandrei
Chanandrei

Reputation: 2421

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

Upvotes: 9

Related Questions