简体   繁体   中英

How to disable an option which is already selected from dropdown list?

In a React project using antd library, I've created a list of options from a json data which is populated as a drop-down list. Following is the code for reference

The json data

const newData = [
  {
    id: 123,
    name: "Vijay"
  },
  {
    id: 345,
    name: "Sanket"
  },
  {
    id: 546,
    name: "Hitesh"
  },
  {
    id: 789,
    name: "Sameer"
  },
  {
    id: 421,
    name: "Akshay"
  }
];

That data is used over here in <Select/>

<h2>Data 1</h2>
    <Select
      onChange={(key, val) => handleOnValuesChange(key, val)}
      placeholder="Select any one"
      style={{ width: 120 }}
      options={newData.map((_) => ({
        label: _.name,
        value: _.id
      }))}
      bordered={false}
    />
    <br />
    <h2>Data 2</h2>
    <Select
      onChange={(key, val) => handleOnValuesChange(key, val)}
      placeholder="Select any one"
      style={{ width: 120 }}
      options={newData.map((_) => ({
        label: _.name,
        value: _.id
      }))}
      bordered={false}
    />

The onChange function

const handleOnValuesChange = (key, val) => {
  const allData = newData.map((data) => {
    if (data.id === val) {
      return {
        ...data,
        disabled: true
      };
    } else {
      return {
        ...data,
        disabled: false
      };
    }
  });
  console.log("NEW DATA", allData);
};

When Vijay and Akshay is selected, I'am expecting the data as

0: {id: 1, value: "Vijay", disabled: true } 
1: {id: 2, value: "Sanket", disabled: false}
2: {id: 3, value: "Hitesh", disabled: false }
3: {id: 4, value: "Sameer", disabled: false }
4: {id: 5, value: "Akshay", disabled: true }

but getting output as

0: {id: 1, value: "Vijay", disabled: false } {/* This disabled should change to true */}
1: {id: 2, value: "Sanket", disabled: false}
2: {id: 3, value: "Hitesh", disabled: false }
3: {id: 4, value: "Sameer", disabled: false }
4: {id: 5, value: "Akshay", disabled: true }

How to tackle this? Any appropriate solution highly appreciated

This is the codesandbox link as: https://codesandbox.io/s/bordered-less-antd-4-17-0-alpha-7-forked-wtur0

you are always using the base newData element. so on each call of handleOnValuesChange you have no value set to disabled.

you need to update the newData or use some other temp variable.

also value is the first parameter for the onChange used by antd select.

let newData = [
  {
    id: 123,
    name: "Vijay",
    disabled: false,
  },
  {
    id: 345,
    name: "Sanket",
    disabled: false,
  },
  {
    id: 546,
    name: "Hitesh",
    disabled: false,
  },
  {
    id: 789,
    name: "Sameer",
    disabled: false,
  },
  {
    id: 421,
    name: "Akshay",
    disabled: false,
  }
];

const handleOnValuesChange = (val) => {
  console.log("VAL", val);
  newData = newData.map((data) => {
    console.log(data, val);
    if (data.id === val) {
      return {
        ...data,
        disabled: true
      };
    }
    return data;
  });
  console.log("NEW DATA", newData);
};

I checked the sandbox code and found multiple issues with your code.

  1. You have to change the newData value with update value otherwise it will old data for render.
  2. You have to compare if (data.id === val.value) instead of if (data.id === val) in handleOnValuesChange function.
  3. You have to return data only in else part.

You can check modified implementation on Sandbox

It will be great if you use the state for newData

The newData should be stored in a state inorder to achieve disabling of options already selected. This is because the DOM gets re-rendered only if props or state is updated.

So in your code since the data is not stored in any state it does not change the non focused option, once the focused option is changed.

I have made some changes to the code and added the working example in sandbox .

  const [data, setData] = React.useState(updatedData); //store the newData with disabled added
  const [prevKey, setPrevKey] = React.useState(null); //store the last changed option



  const handleOnValuesChange = (key, val) => {
    const updating = [...data];
    setPrevKey(val.value);
    data.map((d, i) => {
      if (d.id === val.value) {
        updating[i] = {
          ...d,
          disabled: true
        };
      }
      if (d.id === prevKey) { //this toggles the previous selected value to false
        updating[i] = {
          ...d,
          disabled: false
        };
      }
    });
    setData(updating);
  };



.....
<Select
        onChange={(key, val) => handleOnValuesChange(key, val)}
        placeholder="Select any one"
        style={{ width: 120 }}
        options={data
          .filter((d) => d.disabled === false) //this shows only the options that are not disabled
          .map((_) => {
          console.log(_.name)
          console.log(_.id)
          return({
            label: _.name,
            value: _.id
          })})}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM