How to customize Select to display selected options separated by comma? react-select

Viewed 1215

I tried to customize Select component from react-select library. I customized multiSelectValue with span elements and added commas to labels. but it doesn't work well with input. It works as expected when items selected in dropdown list. But when I try to input value for search options then input is focused, and span items shifts to left, as a result field become empty.

Multiselect

export default function App() {
  const [values, setValues] = useState([]);

  return (
    <div className="root">
      <Select
        styles={styles}
        isSearchable
        isMulti
        getOptionValue={(option) => option["value"]}
        options={options}
        value={values}
        onChange={(options) => {
          setValues(() => options);
        }}
        components={{
          MultiValue: CustomMultiValue
        }}
      />
    </div>
  );
}

Customized selected value

function CustomMultiValue(props) {
  const { getValue, data } = props;

  const selectedOptions = getValue();
  const currentOptionIdx = selectedOptions.findIndex(
    (option) => option.value === data.value
  );

  return (
    <span>
      {data.label}
      {currentOptionIdx === selectedOptions.length - 1 ? "" : ", "}
    </span>
  );
}

enter image description here

Sandbox project https://codesandbox.io/s/boring-knuth-kfo1e?file=/src/CustomMultiValue.js

2 Answers

I don't think there's anything wrong with your code. Maybe your should try to increase the width of the Select so you can see all of the other multi-values which are clipped in your codesandbox.

const width = "500px";
const styles = {
  control: (provided) => ({
    ...provided,
    width
  }),
  menu: (provided) => ({
    ...provided,
    width
  }),
  ...
};

Edit 63939332/how-to-customize-select-to-display-selected-options-separated-by-comma-react-se

I've found a solution. To implement it need to do 2 operations:

  • change overflow styles for ValueContainer when select is open
  • scroll to left when menu is closed

when menu is open use overflow:unset - so input will displayed correctly at the end of selected values when menu is closed use overflow:ellipsis to show first selected values and slice them is needed

  valueContainer: (provided, state) => {
    const disableOverflow =
      state.selectProps.isSearchable && state.selectProps.menuIsOpen;

    return {
      whiteSpace: "nowrap",
      textOverflow: disableOverflow ? "unset" : "ellipsis",
      overflow: "hidden",
      flex: "1 1 0%",
      position: "relative"
    };
  },

To scroll to left need to use custom ValueContainer and pass ref to that container. Checking when menuIsOpen changes to false and at that moment scroll to left.

function CustomMultiValueContainer(props) {
  const {
    selectProps: { menuIsOpen }
  } = props;
  const containerRef = useRef(null);
  const styles = props.getStyles("valueContainer", props);

  useEffect(() => {
    if (!menuIsOpen) {
      if (containerRef && containerRef.current) {
        containerRef.current.scrollLeft = 0;
      }
    }
  }, [menuIsOpen]);

  return (
    <div ref={containerRef} style={styles}>
      {props.children}
    </div>
  );
}
Related