React select multiple true- comma separated value display - reactjs

Is it possible to get the display of selected values as comma separated.. instead of the box with cross sign
import Select from 'react-select'
<Select
name=''
styles={customStyles}
isClearable
isMulti
/>

You can create your own custom MultiValueContainer component. To display comma separated options, we can do something like this:
render() {
const components = {
MultiValueContainer: ({ selectProps, data }) => {
const values = selectProps.value;
if (values) {
return values[values.length - 1].label === data.label
? data.label
: data.label + ", ";
} else return "";
}
};
return (
<Select
value={this.state.value}
onChange={this.handleChange}
isMulti
name="colors"
options={colourOptions}
className="basic-multi-select"
classNamePrefix="select"
components={components}
/>
);
}
here is the code sandbox link to see above code in action.

According to the React-Select docs, you can change the styles of the individual selected items.
But, they render as boxes with x buttons on them so that the user can choose to de-select any of the selected items.
I would suggest playing with the React-Select styles like this:
<Select
styles={customStyles}
/>

Related

How to define a max limit of options in react-select?

I created a react select component for my app react and I have more than 70 options, for that I want to define a max limit of options that the user can choose to handle it well. Can you please help me?
The code:
export default function ReactSelect(props) {
const animatedComponents = makeAnimated();
return (
<Select
isMulti="true" // allow to select mutli options
isRtl="true" // right to left
name="name" // html name
options={accountsNames} // options
className="basic-multi-select"
classNamePrefix="select"
isSearchable="true" // searchable for the closest one
placeholder="اختر اسم الحساب..." // if there is no option selected
components={animatedComponents}
/>
);
}
You can control the selected options state and disable the options conditionally based on selectedOptions.length like this:
const [selectedOptions, setSelectedOptions] = React.useState([]);
return (
<Select
isMulti
value={selectedOptions}
onChange={(o) => setSelectedOptions(o)}
options={colourOptions}
// only allow user to choose up to 3 options
isOptionDisabled={() => selectedOptions.length >= 3}
className="basic-multi-select"
classNamePrefix="select"
/>
);
Live Demo
This might help:
const MultiSelect = ({valueList, onChange, options, maxLimit = 5}) => {
return (
<Select
value={valueList}
isMulti
onChange={onChange}
options={options}
isOptionDisabled={(option) => valueList.length >= maxLimit}
/>
);
};

Material UI MenuItem not showing selected item with hardcoded values

I am using material-ui MenuItem like the following and noticing following issue. I have hardcoded the Yes or No values and on the UI, my dropdown looks like following:
Image 1:
When I click on dropdown icon, it shows me the following:
Image 2:
When i select Yes or No,my selection doesn't stays on the screen and after selecting , it goes back to look exactly like Image 1. Why it is happening? I noticed that this is happening with hardcoded values only. All other places where I am displaying dynamic data via api call is showing the selected item on screen.
Here is my code snippet:
<CustomSelectDropdown name="yesornofordata" type="select" placeholder="Is the data approved?"/>
const CustomSelectDropdown = ({
placeholder,
disabled,
...props
}) => {
const [field, meta] = useField(props);
const errorText = meta.error && meta.touched ? meta.error : "";
return (
<div>
<InputLabel id="selectLabel">{placeholder}</InputLabel>
<Field
labelId={placeholder}
{...field}
disabled={disabled}
as={StyledSelect}
error={!!errorText}>
<MenuItem data-selected-value={'Y'} onClick={handleSelectedAnswer}>Yes</MenuItem>
<MenuItem data-selected-value={'N'} onClick={handleSelectedAnswer}>No</MenuItem>
</Field>
</div>
);
};
Added code for the function :
const handleSelectedAnswer = event => {
const { selectedValue } = event.currentTarget.dataset;
console.log("Storing selected answer in session storage ")
sessionStorage.setItem("selectedAnswer", selectedValue)
}

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:
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.
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>
);
};
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 }}
/>

Adding some text next to an option in react-select based on the value

I am working with react-select and need to add the text as in the image 'default category' based on some condition. Any way to achieve this?
My code:
renderCategories(categories) {
const temp = [];
categories.forEach((key) => {
temp.push({label: key.name, value: key.id.toString()});
});
return temp;
}
<Field
name="event_category"
component={renderSelectField}
placeholder="Select Event Category"
options={this.renderCategories(categories)}
/>
where renderSelectField is the Select component of react-select, using redux-form and categories is an array of objects containing id and name.
You can do this by providing your own custom Option template to react-select. Works a little like:
const OptionLayout = props => {
const { innerProps, innerRef } = props;
return (
<article ref={innerRef} {...innerProps} className={'custom-option'}>
<h4>{props.data.artist}</h4>
<div className={'sub'}>{props.data.title} </div>
</article>
);
};
<Select {...selectProps} components={{Option: OptionLayout}} />
That's not a match for your layout, but should give you what you need to create your own custom Option template.

react-select How to hide dropdown menu programmatically when 'no results found' is shown?

Github Repo: react-select
After searching in the select box:
After typing a text that is not in the dropdown and enter is pressed. I want to hide the dropdown box.
My implementation:
<Select
ref={ input => this.input = input }
name="form-field-name"
searchable
autoBlur
clearable={false}
openOnFocus
onInputKeyDown={this.onInputKeyDown.bind(this)}
value={this.state.selectedOption}
onChange={this.handleChange.bind(this)}
options={this.props.items}
/>
using onInputKeyDown I am detecting enter keycode. What do I do to remove the dropdown there when 'No results found' is shown?
onInputKeyDown(e) {
if (e.keyCode === keys.ENTER) {
console.log('on input key down');
// How to detect 'No results found' shown?
// And then, how to close the dropdown?
}
}
In V2 you can achieve this by setting noOptionsMessage to a function that returns null:
<Select noOptionsMessage={() => null}/>
This will prevent the fallback option from displaying completely. Note that setting noOptionsMessage to null directly will result in an error, the expected prop type here is a function.
First method:
Turn off <Menu /> component to hide dropdown list.
<Select
components={{
...components,
Menu: () => null
}}
/>
Second method:
Turn off dropdown conditionally. e.g. When there is no value in input.
// Select.js
import { Menu } from './Menu'
<Select
{...props}
components={{
Menu
}}
/>
-------
// Menu.js
import { components } from 'react-select'
export const Menu = props => {
if (props.selectProps.inputValue.length === 0) return null
return (
<>
<components.Menu {...props} />
</>
)
}
Try using the noResultsText prop. Set it to null whenever you would want to hide it.
If you want to hide the menu when no more options are available you can try to override the MenuList component. This worked for me:
const MenuList = ({ children, ...props }: MenuListProps) => {
return Array.isArray(children) && children?.length > 0 ? (
<components.MenuList {...props}>
{children}
</components.MenuList>
) : null;
};

Resources