Material UI Select Field multiselect - reactjs

I tried several times the example given in the documentation. but it didn't work well for me.
can any one help me....
this is the code
import React, {Component} from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
/**
* `SelectField` can handle multiple selections. It is enabled with the `multiple` property.
*/
export default class SelectFieldExampleMultiSelect extends Component {
state = {
values: [],
};
handleChange = (event, index, values) => this.setState({values});
menuItems(values) {
return names.map((name) => (
<MenuItem
key={name}
insetChildren={true}
checked={values && values.indexOf(name) > -1}
value={name}
primaryText={name}
/>
));
}
render() {
const {values} = this.state;
return (
<SelectField
multiple={true}
hintText="Select a name"
value={values}
onChange={this.handleChange}
>
{this.menuItems(values)}
</SelectField>
);
}
}
http://www.material-ui.com/#/components/select-field
the select property works but it doesnt select multiple options. when i check the states.value it only includes a single value not a array of values

This example didn't work for me either. To add the multi-select feature you have to manually add the new value to the state, so the handleChange function from the example would look something like this:
handleChange(event, index, values) {
this.setState({
values: [...this.state.values , values]
});
}
EDIT: I updated my version of material-ui to the latest stable version and their example worked like a charm

A much better approach is possible. In the lasted version of material UI.
import Select from '#material-ui/core/Select';
import MenuText from '#material-ui/core/MenuText';
import {useState} from 'react';
const App = () => {
const [selected,setSelected] = useState([]);
return <Select multiple={true} value={selected} onChange={(event) => setSelected(event.target.value)}>
<MenuItem>Val - 1</MenuItem>
<MenuItem>Val - 2</MenuItem>
<MenuItem>Val - 3</MenuItem>
<MenuItem>Val - 4</MenuItem>
</Select>
}
Make sure to set the value of select as an array. Otherwise, It will not work

This worked for me for old material ui version. You can add multiple items and deselect to remove them.
handleChange(event, index, values) {
this.setState({
values: [...values]
});
}

Related

Autocomplete Material UI search based on two attributes

I have this data:
const sample = [
{hero: 'DARTH VADER', faction: 'EMPIRE'},
{hero: 'LUKE SKYWALKER', faction: 'REBEL'},
{hero: 'GREEDO', faction: 'BOUNTY HUNTER'},
];
Using Autocomplete, I am able to search the value via either hero or faction attribute by assigning one of them in getOptionLabel={(option) => {option.hero}} or getOptionLabel={(option) => {option.faction}} prop.
However I would like to be able to search using both of these attributes at the same time (typing either DARTH VADER or EMPIRE will return the same result).
The questions are as follows:
Can I achieve that using a single autocomplete?
If not, can we use a toggle to change which attribute to look for in the autocomplete?
Many thanks
Autocomplete provides the filterOptions prop.
you can use it to provide a custom filter like so (here's a codesandbox):
import React from 'react';
import TextField from '#material-ui/core/TextField';
import Autocomplete, { createFilterOptions } from '#material-ui/lab/Autocomplete';
const filterOptions = createFilterOptions({
matchFrom: 'any',
stringify: (option) => option.hero + option.faction,
});
export default function Filter() {
return (
<Autocomplete
id="filter-demo"
options={sample}
getOptionLabel={(option) => option.hero}
filterOptions={filterOptions}
renderInput={(params) => <TextField {...params} label="Custom filter" variant="outlined" />}
/>
);
}
const sample = [
{hero: 'DARTH VADER', faction: 'EMPIRE'},
{hero: 'LUKE SKYWALKER', faction: 'REBEL'},
{hero: 'GREEDO', faction: 'BOUNTY HUNTER'},
];

Dropdown menu in React, filter through list

I am building a rest countries app in react and I'm trying to filter by region through a list. I would like to use a dropdown menu. I have tried using react select, creating a new component, this is my code
const DropdownMenu = (props) => {
const options = [
'', 'Africa', 'America', 'Asia', 'Europe', 'Oceania'
];
const defaultOption = options[0];
const handleFilterInput = (event) => {
let value = event.target.options;
props.handleRegionSearch(value);
};
return(
<div>
<Select options={options} onChange={handleFilterInput} value={defaultOption} placeholder="Select a region"/>
</div>
)
}
export default DropdownMenu;
My problem is, I can not get the value to change to the option selected, therefore it's impossible for me to filter the list I took from the api.
Does anyone have a possible solution for this?
Thanks
You are setting the value wrong
value={defaultOption}
This default option is never changing.
What you can do is catch the current value from onChange() and set the value somewhere (preferably in state) and then use that stored value as the value of dropdown component
Something like this.
const options = [
'', 'Africa', 'America', 'Asia', 'Europe', 'Oceania'
];
const [selectedValue , setSelectedValue ] = useState(options[0]);
const handleFilterInput = (event) => {
let value = event.target.options;
setSelectedValue(value);
props.handleRegionSearch(value);
};
return(
<div>
<Select options={options} onChange={handleFilterInput} value={selectedValue} placeholder="Select a region"/>
</div>
)
Thanks! In the end, I used a react-select component which did solve a this issue on it's own.

react-select property name for value

I have this code:
import React from "react";
import ReactDOM from "react-dom";
import Select from "react-select";
const optionsExample = [
{
code: "CLP",
country: "CLP",
minimumAmount: 10000
},
{
code: "USD",
country: "US",
minimumAmount: 25000
}
];
const handleChange = (newValue, actionMeta) => {
console.log("change newValue", newValue); // object changes but it's not selected the right one
};
const CustomControl = () => (
<Select
defaultValue={optionsExample[0]}
formatOptionLabel={({ code }) => code}
options={optionsExample}
onChange={handleChange}
/>
);
ReactDOM.render(<CustomControl />, document.getElementById("root"));
It doesn't work ok because react-select expect that the value of each object on the data array be named value. How can I pass data like in the example? I need that data has those properties, I can't change country to value.
Actually, I used the props formatOptionLabel to change the default label field from the object to code but I don't know how to do the same but for the value.
Demo with my code, with the problem:
https://codesandbox.io/s/react-select-formatoptionlabel-forked-deuw1?file=/index.js:0-756
This is working because each object has it's value field and that's what is expected by react-select
https://codesandbox.io/s/react-select-formatoptionlabel-forked-d9bdj
If you can't move the mountain, then walk around it.
use inline .map to convert your array of objects
const CustomControl = () => (
<Select
defaultValue={optionsExample[0]}
formatOptionLabel={({ code }) => code}
options={optionsExample.map(x => ({ value: x.country, label: x.code })}
onChange={handleChange}
/>
);
or better still use useMemo to create a new array, if your array changes
const selectOptions = useMemo(() => optionsExample.map(x => ({ value: x.country, label: x.code }),[optionsExample])
<Select
defaultValue={selectOptions[0]}
formatOptionLabel={({ code }) => code}
options={selectOptions}
onChange={handleChange}
/>

material ui : selectfiled multiple property

I'm using material ui, and I want to use the mutliple property, but I have an error :
multiple does not exist on the type selectfiled
<SelectField
multiple={true} //it doesn't work
value={this.state.valueProfession}
onChange={this.handleChangeProfession}></SelectField>
I have the version 0.16.5 of material ui. I would like to avoid to update the last version of material ui. Is there other solution ? Thank you
Please update your version 0.16.5 to newer version in order to use this.
I've used this in version 0.18.4
Here is the simple working example
import React from 'react';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
const names = [
'Oliver Hansen',
'Van Henry',
'April Tucker',
'Ralph Hubbard',
'Omar Alexander',
'Carlos Abbott',
'Miriam Wagner',
'Bradley Wilkerson',
'Virginia Andrews',
'Kelly Snyder',
];
/**
* `SelectField` can handle multiple selections. It is enabled with the `multiple` property.
*/
export default class SelectFieldExampleMultiSelect extends React.Component {
state = {
values: [],
};
handleChange = (event, index, values) => this.setState({values});
menuItems(values) {
return names.map((name) => (
<MenuItem
key={name}
insetChildren={true}
checked={values && values.indexOf(name) > -1}
value={name}
primaryText={name}
/>
));
}
render() {
const {values} = this.state;
return (
<SelectField
multiple={true}
hintText="Select a name"
value={values}
onChange={this.handleChange}
>
{this.menuItems(values)}
</SelectField>
);
}
}

Multi select from react-select with redux-form not working as intended

So iam using multi select from react-select with redux-form with the onBlur hack(?) which is working fine behind the curtain because when i submit it I have the selected data in values
BUT after visiting any multi select field (even if i dont select anything) I end up with no values at all (nothing is displayed but this
))
const options = [
{ value: 'one', label: 'One' },
{ value: 'two', label: 'Two' }
];
<Select
value="one"
options={options}
multi={true}
{...input}
onBlur={() => {
input.onBlur({...input.value})
}
}
/>
So i end up with values in the redux state but I cant see any values in the field. Anyone know why is this happening?
Here's example how to make it works. react-select (1.0.0-rc.2), redux-form (5.3.4)
SelectInput.js
import React from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
export default (props) => (
<Select
{...props}
value={props.input.value}
onChange={(value) => props.input.onChange(value)}
onBlur={() => props.input.onBlur(props.input.value)}
options={props.options}
/>
);
MyAwesomeComponent.js
import React, {PureComponent} from 'react';
import SelectInput from './SelectInput.js';
class MyAwesomeComponent extends PureComponent {
render() {
const options = [
{'label': 'Germany', 'value': 'DE'},
{'label': 'Russian Federation', 'value': 'RU'},
{'label': 'United States', 'value': 'US'}
];
return (
<Field
name='countries'
options={options}
component={SelectInput}
multi
/>
)
};
I have not used more modern versions of react-select, but a year ago, there were some issues with having to split() the string value by the delimiter to get the values as an array, and then join() them again to give to the component.
Stuff like this:
if (multi) {
selectValue = value ? value.join(delimiter) : ''
} else {
selectValue = value || null
}
I recommend examining exactly what the value is in Redux, using Redux DevTools, and what value prop is getting passed to react-select. I'm sure you'll find the problem in there.

Resources