'How to change style of react-select selected options?

Right now react-select shows selected options like this enter image description here

But if we select 10 options out of 20 then this block expands. So instead of displaying each selected option, it will be better if it shows only first selected option + remaining selected option count like this

enter image description here

how can I achieve this in react-select?



Solution 1:[1]

I just made this little piece of code I think it can help you. Here is the live link https://djdz48.csb.app/ and a snippet below:

const App = () => {
  const maxOptions = 2; // You can change the value

  const [values, setValues] = useState([]); // All values (in console)
  const [maxValues, setMaxValues] = useState({});
  const [isMaxVal, setIsMaxVal] = useState(false);

  const [actualOptions, setActualOptions] = useState(options);

  const handleChange = (e) => {
    let els = [];
    e.map((el) => els.push(el));

    if (els.length > maxOptions || values.length > maxOptions) {
      if (els.length === 0) {
        setValues(els);
        setIsMaxVal(false);
      } else {
        setIsMaxVal(true);

        const val = {
          key: 1,
          label: values[0]["label"] + " +" + (values.length + 1).toString()
        };

        setValues((values) => {
          return [...values, els[els.length - 1]];
        });

        setMaxValues(val);

        let opt = [];

        options.map((el) => {
          if (!values.includes(el) && !els.includes(el)) {
            opt.push(el);
          }
        });

        setActualOptions(opt);
      }
    } else {
      setValues(els);
    }
  };

  // values in real time

  useEffect(() => {
    console.log(values);
  }, [values]);

  return (
    <div className="App">
      <Select
        options={isMaxVal ? actualOptions : options}
        isMulti={true}
        onChange={(e) => handleChange(e)}
        value={values.length <= maxOptions ? values : maxValues}
      />
    </div>
  );
};

export default App;

Solution 2:[2]

As far as I know, this can not be done directly through react-select props, but you can create your custom wrapper to have the desired functionality.

Another approach is to write your custom component and pass it to the Select component like this:

<Select
  isMulti
  isClearable
  options={options}
  closeMenuOnSelect={false}
  components={{
    MultiValue: CustomMultiValue
  }}
/>

react-select allows you to write your custom component and use it. So, here's what I've done. First, I've looked for the component I want to modify and write a custom component. There should be different possibilities, but I've decided to write a custom MultiValue component. Then, I've copied the code from the react-select repository and modified it.

Try a working sandbox here

The new custom component checks if it is the third selected option. If it is the first or the second option, it works like the original component. If it is the third option, it prints the number, and if it's another option, it prints nothing.

const CustomMultiValue = <
  Option,
  IsMulti extends boolean,
  Group extends GroupBase<Option>
>(
  props: MultiValueProps<Option, IsMulti, Group>
) => {
  const {
    children,
    className,
    components,
    cx,
    data,
    getStyles,
    getValue,
    index,
    innerProps,
    isDisabled,
    removeProps,
    selectProps
  } = props;

  const { Container, Label, Remove } = components;

  const additionalItems = getValue().length - MAX_ITEMS;

  return (
    <ClassNames>
      {({ css, cx: emotionCx }) => (
        <>
          {index < 2 ? (
            <Container
              data={data}
              innerProps={{
                className: emotionCx(
                  css(getStyles("multiValue", props)),
                  cx(
                    {
                      "multi-value": true,
                      "multi-value--is-disabled": isDisabled
                    },
                    className
                  )
                ),
                ...innerProps
              }}
              selectProps={selectProps}
            >
              <Label
                data={data}
                innerProps={{
                  className: emotionCx(
                    css(getStyles("multiValueLabel", props)),
                    cx(
                      {
                        "multi-value__label": true
                      },
                      className
                    )
                  )
                }}
                selectProps={selectProps}
              >
                {children}
              </Label>
              <Remove
                data={data}
                innerProps={{
                  className: emotionCx(
                    css(getStyles("multiValueRemove", props)),
                    cx(
                      {
                        "multi-value__remove": true
                      },
                      className
                    )
                  ),
                  "aria-label": `Remove ${children || "option"}`,
                  ...removeProps
                }}
                selectProps={selectProps}
              />
            </Container>
          ) : index === 2 ? (
            <Container
              data={data}
              innerProps={{
                className: emotionCx(
                  css(getStyles("multiValue", props)),
                  cx(
                    {
                      "multi-value": true,
                      "multi-value--is-disabled": isDisabled
                    },
                    className
                  )
                ),
                ...innerProps
              }}
              selectProps={selectProps}
            >
              <Label
                data={data}
                innerProps={{
                  className: emotionCx(
                    css(getStyles("multiValueLabel", props)),
                    cx(
                      {
                        "multi-value__label": true
                      },
                      className
                    )
                  )
                }}
                selectProps={selectProps}
              >
                {`+ ${additionalItems}`}
              </Label>
            </Container>
          ) : null}
        </>
      )}
    </ClassNames>
  );
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 yousoumar
Solution 2 crls_b