Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple dropdowns implementation with one main dropdown

Tags:

I'm using dropdowns from PrimeReact. I have to implement them so that the values ​​from the first upper main dropdown change the values ​​of all the lower ones, which I already did, but then I need than each dynamically dropdown from the lower block have to change change only its unique value:

screenshot

I cannot understand how to implement it.

This is my code :

    class LeagueCard extends Component {

  state = {
    selectedItemDefaultDropDown: this.props.cardContent.insuranceVariants[0],
    selectedItemPersonallyDropDown: null
  };

  createOptions = (arr) => {
    return arr.map(item => ({label: item, value:item}))
  };


  render() {
    const {
      cardIndex, cardContent: {
        insuranceVariants,
        price,
      },
    } = this.props;


    const insuranceOptions = this.createOptions(insuranceVariants);


    return (
        <>
          <div className={styles.header}>
            <h4>League {cardIndex + 1}</h4>
            <h4>Total {price.reduce((a, b) => a + b)} PLN</h4>
          </div>
          <div className={styles.defaultDropDownWrapper}>
            <p>Default variant of the insurance program</p>
            <Dropdown //MAIN DROPDOWN WORKS PERFECTLY
                value={this.state.selectedItemDefaultDropDown}
                options={insuranceOptions}
                onChange={e => {
                  this.setState({ selectedItemDefaultDropDown:e.value });
                }}
            />
          </div>
          <table>
            <thead>
            <tr>
              <th className={styles.columnName}>#</th>
              <th className={styles.columnName}>FIRST AND LAST NAME</th>
              <th className={styles.columnName}>AGE</th>
              <th className={styles.columnName}>VARIANT OF THE INSURANCE PROGRAM</th>
            </tr>
            </thead>
            <tbody>
            {insuranceVariants.map((item, index) =>
                <tr key={index} className={(index + 1) % 2 === 0 ? styles.evenTabStyle : styles.baseTabStyle}>
                  <td>{index + 1}</td>
                  <td>Jan Nowak</td>
                  <td>20</td>
                  <td>
                    <Dropdown //SECONDARY DYNAMICALLY DROPDOWNS WITH TROUBLES
                        value={this.state.selectedItemDefaultDropDown}
                        options={insuranceOptions}
                        onChange={e => {
                          this.setState({ selectedItemDefaultDropDown: e.value});
                        }}
                    />
                  </td>
                </tr>)}
            </tbody>
          </table>
        </>
    );
  }
}
like image 538
ZhaZha Avatar asked Jan 04 '20 12:01

ZhaZha


1 Answers

There is various way to achieve this but the most simple way I can think of right now is following

Because you have 3 dropdown ( in this case ) so you need to keep 3 entry in state for each dropdown

keep your state something like this

{
  primaryDropdown: 'selected option',
  secondaryDropdowns: ['selected value for first', 'selected value for second']
}

I am keeping array because you can change the number of secondary dropdown dynamically

now the onChangeHandler for primary dropdown will look like this

primaryOnChangeHander(selected) {
 this.setState(prevState => {
  const newState = { 
    ...prevState,
    primaryDropdown: selected,
    secondaryDropdowns: prevState.secondaryDropdowns.map(item => selected )
  };
  return newState;
 })
}

when primary dropdown changes you are going to update the primary dropdown and secondary dropdowns as well

and onChangeHander for secondary dropdown looks like

 secondaryOnChangeHander (selected, indexOfDropdown) {
  this.setState(prevState => ({
    ...prevState,
    secondaryDropdowns: prevState.secondaryDropdowns.map((item, index) => {
      if (index === indexOfDropdown) {
        return selected;
      } else {
       return item;
      }
    })
  }))
}

When secondary dropdown value changes you only update that perticular dropdowns value


your code will now look like this

/* important note here: assuming that insuranceVariants is a fixed length array */
class LeagueCard extends Component {

  state = {
    /* better would be to create a variable for `this.props.cardContent.insuranceVariants[0]` and use that */
    primaryDropdown: this.props.cardContent.insuranceVariants[0],
    secondaryDropdowns: [this.props.cardContent.insuranceVariants.map(item => this.props.cardContent.insuranceVariants[0]]
  };

  createOptions = (arr) => {
    return arr.map(item => ({label: item, value:item}))
  };

  primaryOnChangeHander(selectedValue) {
    this.setState(prevState => {
      const newState = { 
        ...prevState,
        primaryDropdown: selectedValue,
        secondaryDropdowns: prevState.secondaryDropdowns.map(item => selectedValue)
      };
      return newState;
    })
  }

  secondaryOnChangeHander (selectedValue, indexOfChangedDropdown) {
    this.setState(prevState => ({
      ...prevState,
      secondaryDropdowns: prevState.secondaryDropdowns.map((item, index) => {
        if (index === indexOfChangedDropdown) {
          return selectedValue;
        } else {
          return item;
        }
      })
    }));
  }

  render() {
    const {
      cardIndex, cardContent: {
        insuranceVariants,
        price,
      },
    } = this.props;


    const insuranceOptions = this.createOptions(insuranceVariants);


    return (
      <>
        <div className={styles.header}>
          <h4>League {cardIndex + 1}</h4>
          <h4>Total {price.reduce((a, b) => a + b)} PLN</h4>
        </div>
        <div className={styles.defaultDropDownWrapper}>
          <p>Default variant of the insurance program</p>
          <Dropdown //MAIN DROPDOWN WORKS PERFECTLY
            value={this.state.primaryDropdown}
            options={insuranceOptions}
            onChange={e => {
              this.primaryOnChangeHander(e.value);
            }}
          />
        </div>
        <table>
          <thead>
            <tr>
              <th className={styles.columnName}>#</th>
              <th className={styles.columnName}>FIRST AND LAST NAME</th>
              <th className={styles.columnName}>AGE</th>
              <th className={styles.columnName}>VARIANT OF THE INSURANCE PROGRAM</th>
            </tr>
          </thead>
          <tbody>
            {insuranceVariants.map((item, index) =>
            <tr key={index} className={(index + 1) % 2 === 0 ? styles.evenTabStyle : styles.baseTabStyle}>
              <td>{index + 1}</td>
              <td>Jan Nowak</td>
              <td>20</td>
              <td>
                <Dropdown //SECONDARY DYNAMICALLY DROPDOWNS WITH TROUBLES
                  value={this.state.secondaryDropdowns[index]}
                  options={insuranceOptions}
                  onChange={e => {
                    this.secondaryOnChangeHander(e.value, index);
                  }}
                />
              </td>
            </tr>)}
          </tbody>
        </table>
      </>
    );
  }
}

like image 50
Tripurari Shankar Avatar answered Oct 02 '22 16:10

Tripurari Shankar