简体   繁体   English

如何禁用已从下拉列表中选择的选项?

[英]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.在使用 antd 库的 React 项目中,我从 json 数据创建了一个选项列表,该数据填充为下拉列表。 Following is the code for reference以下是代码供参考

The json data json数据

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/>该数据在<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 onChange 函数

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选择Vijay和Akshay时,我期待数据

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这是代码和框链接: https ://codesandbox.io/s/bordered-less-antd-4-17-0-alpha-7-forked-wtur0

you are always using the base newData element.您始终使用基本的 newData 元素。 so on each call of handleOnValuesChange you have no value set to disabled.所以在每次调用 handleOnValuesChange 时,您都没有将值设置为禁用。

you need to update the newData or use some other temp variable.您需要更新 newData 或使用其他一些临时变量。

also value is the first parameter for the onChange used by antd select. value 也是 antd select 使用的 onChange 的第一个参数。

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.您必须使用更新值更改newData值,否则它将旧数据用于渲染。
  2. You have to compare if (data.id === val.value) instead of if (data.id === val) in handleOnValuesChange function.您必须在 handleOnValuesChange 函数中比较if (data.id === val.value)而不是if (data.id === val)
  3. You have to return data only in else part.您只需返回其他部分的数据。

You can check modified implementation on Sandbox您可以在Sandbox上检查修改后的实现

It will be great if you use the state for newData如果您将 state 用于newData

The newData should be stored in a state inorder to achieve disabling of options already selected. newData 应该存储在一个状态中,以便禁用已经选择的选项。 This is because the DOM gets re-rendered only if props or state is updated.这是因为只有在更新 props 或 state 时才会重新渲染 DOM。

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 .我对代码进行了一些更改,并在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
          })})}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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