Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Select - Multi Select custom way to display multiple options

I am looking to customize the multiselect and the way we create the display of showing selected options.

Right now, with many options selected the select component takes up a prohibitive amount of space for certain UIs. See example:

enter image description here

I'd like to utilize the out of the box chip display for selected options within the input, but I only want to show only a few selected options (like 3/4 max) and then add a "badge" count for the number of selected options that aren't shown in the value container in the input. The options that are selected but are past the max number of chips allowed to show in the input should show as selected within the dropdown list, while the chips that do show's values should not show in our dropdown.

I've implemented part of this with using a custom ValueContainer to show only the first few chip selections, and then adding a count of additional/"overflow" selections. I'm unsure of how I can utilize the prop hideSelectedOptions to achieve this to show selected items in the list only when my max is met without showing all of them since this prop takes a boolean.

enter image description here

Here's what I have so far: https://codesandbox.io/s/custom-react-select-sjtib


import React, { Component } from "react";
import Select, { components } from "react-select";
import { colourOptions } from "./docs/data";
import "./example.css";

class CustomSelect extends Component {
  state = {
    values: []
  };

  handleChange = values => {
    this.setState({ values });
  };

  render() {
    const { values } = this.state;
    return (
      <div>
        <Select
          hideSelectedOptions={values.length < 3 ? true : false}
          isMulti
          options={colourOptions}
          onChange={this.handleChange}
          value={values}
          components={{ ValueContainer }}
        />
      </div>
    );
  }
}

export default CustomSelect;

const ValueContainer = ({ children, getValue, ...props }) => {
  let maxToShow = 3;
  var length = getValue().length;
  let displayChips = React.Children.toArray(children).slice(0, maxToShow);
  let shouldBadgeShow = length > maxToShow;
  let displayLength = length - maxToShow;

  return (
    <components.ValueContainer {...props}>
      {!props.selectProps.inputValue && displayChips}
      <div className="root">
        {shouldBadgeShow &&
          `+ ${displayLength} item${length != 1 ? "s" : ""} selected`}
      </div>
    </components.ValueContainer>
  );
};
like image 986
user10782250 Avatar asked Nov 15 '19 01:11

user10782250


People also ask

How do you select multiple options in react?

The first and foremost thing we need to do is change the select element and make it let use select multiple values. The second thing we need to change is the constructor method and add an array so that we can use that array to store multiple selections from the user.


1 Answers

I would personally keep hideSelectedOptions={false} and go for styles property usage (options property to be more exact) and setting display: 'none' for the ones which shouldn't be visible:

const styles = {
    option: (base, value) => {
        return (shouldBeShown(value) ? { ...base } : { display: 'none'});
    }
};

shouldBeShown(value) is a custom function for checking if the particular option should be shown. In order to get option data you can use value.data.

Then you can set styles={styles} in Select component:

<Select
    hideSelectedOptions={false}
    isMulti
    styles={styles}
    onChange={this.handleChange}
    options={options}
    value={values}
    components={{ ValueContainer }}
/>
like image 165
cohnred Avatar answered Sep 21 '22 14:09

cohnred