When on Select field I hit space, first value from options is being selected. How to disable such behaviour?
<Select
ref={r => (this.selectRef = r)}
className="basic-single"
classNamePrefix="select"
onInputChange={val => {
console.log('va', val)
this.setState({ inputValue: val })
}}
inputValue={this.state.inputValue}
options={[{ value: 'aaa', label: 'aaa bbb' }, { value: 'bbb', label: 'bbb ccc' }]}
name="color"
/>
HERE IS A DEMO
I would suggest to use the onKeyDown props and prevent the action when the use hits the space bar so nothing will be selected.
<Select
ref={r => (this.selectRef = r)}
className="basic-single"
classNamePrefix="select"
onInputChange={val => {
this.setState({ inputValue: val });
}}
onKeyDown={e => {
if (e.keyCode === 32 && !this.selectRef.state.inputValue) e.preventDefault();
}}
inputValue={this.state.inputValue}
options={[
{ value: "aaa", label: "aaa bbb" },
{ value: "bbb", label: "bbb ccc" }
]}
name="color"
/>
Live example here.
Related
In a list of certain records where I'm populating in the dropdown of an input component. The default value is set on page loading but, I need to update it on click event of a button. Refer to the code below.
Home.js
const allList = [
{ id: "1", value: "Fruits" },
{ id: "2", value: "Vegetables" },
{ id: "3", value: "Grains" },
{ id: "4", value: "Milk" },
{ id: "5", value: "Meat" },
{ id: "6", value: "Fish" },
{ id: "7", value: "Pulses" }
];
const [itemList, setItemList] = useState(allList);
const [newValue, setNewValue] = useState(allList[0].value)
// I want to set the value on click of cancel button
const handleCancel = (e) => {
setNewValue(allList[2].value)
setPopup(false);
};
return (
<>
<DataList
defaultValue={newValue}
list="itemListOptions"
id="itemList"
placeholder="Search/select items"
data={itemList}
onSelectionChange={itemChanged}
></DataList>
{popup === true ? (
<Popup okbtnClick={handleOK} canclebtnclick={handleCancel} />
) : null}
</>
)
DataList.js
<input
defaultValue={props?.defaultValue ?? ""}
className="form-control cpselect"
id={props?.id ?? ""}
list={props?.list ?? ""}
placeholder={props?.placeholder ?? ""}
onChange={props?.onSelectionChange ?? ""}
/>
<datalist key={props.id} id={props?.list ?? ""}>
{props.data.map((d) => {
return <option key={d.id} id={d.id} value={d.value}></option>;
})}
</datalist>
My intention is to change the defaultValue inside the input field, on click of cancel button. Here it loads the first element and on click event should load third element. What is the best optimal solution?
Please refer to the Codesandbox link: https://codesandbox.io/s/clever-rumple-ig0wwj
What you want to do is to use value instead of defaultValue.
defaultValue property is configured in such a way that it reads the prop only once and then creates an inner state that handles changes.
In case of multi-select , can someone help me with the onChange function ?
What can I pass inside updateFormState( ) to make the code work. Thanks.
const formState = {
fruits: "",
};
function updateFormState(key, value) {
formState[key] = value;
}
const [fruits] = useState([]);
<Form.Label>fruits</Form.Label>
<MultiSelect
options={[
{ label: "Grapes 🍇", value: "grapes" },
{ label: "Mango 🥭", value: "mango" },
{ label: "Strawberry 🍓", value: "strawberry", disabled: true },
]}
id="fruits"
labelledBy="Select"
value={fruits}
onChange={(e) => updateFormState( )}
/>
</Form.Group>
hi try this i hope it usefull
const [fruits, setFruits] = useState();
console.log("fruits",fruits);
return (
<div>
<select onChange={(e) => setFruits(e.target.value)} value={fruits}>
<option value='' selected disabled hidden>
select a fruits
</option>
<option value='apple'>apple</option>
<option value='banana'>banana</option>
<option value='orange'>orange</option>
</select>
</div>
);
I have a set of select menus and I am trying to change a value when I select an option using onChange={updateValue} event. When I first select an option, the value is not being updated in the select menu.
It only changes the second time I try to choose an option. Not sure what I am doing wrong.
Edit: I did some more research (OnChange event using React JS for drop down) and I believe I need the value of the select to be updated as well, using setState. I cant figure out how to do it without having a variable for each value and set the state again.
let selectMenus = [
{
id: 'id1',
name: 'name1',
label: 'label1',
value: '0',
options: [
{
text: 'All ages',
value: '0',
},
{
text: '35 - 37 yrs',
value: '1',
},
],
buttonLabel: 'Refresh',
},
{
id: 'id2',
name: 'name2',
label: 'label2',
value: '1',
options: [
{
text: 'All ages',
value: '0',
},
{
text: '45 - 50 yrs',
value: '1',
},
],
buttonLabel: 'Refresh',
},
];
const [url, setUrl] = useState('http://localhost:5000/selectDropdowns1');
const updateValue = () => {
setUrl('http://localhost:5000/selectDropdowns2');
};
<form>
{selectMenus.map((select) => (
<div key={select.id} className='select-container'>
<label htmlFor={select.id}>{select.label}</label>
<select id={select.id} name={select.name} value={select.value} onChange={updateValue}>
{select.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{select.buttonLabel}</button>
</div>
))}
</form>;
The problem is that when you provide onChange prop to select component it become a controlled component.
For more information: React Docs - Forms #controlled components
When you dealing with controlled components you must provide a value to it and when onChange triggerd it should update that value to work properly. Since you did not provide the full code, I imagine you have an array of select menus and options attached to it.
So in this case every select component should have own onChange method and own value to work properly. To achive this we should create another component for only Select Options. Like this;
function SelectComponent({ optionList, onSelected }) {
const [value, setValue] = useState();
const updateValue = ({ target }) => {
setValue(target.value);
if (onSelected) onSelected(target.value);
};
return (
<>
<label htmlFor={optionList.id}>{optionList.label}</label>
<select
id={optionList.id}
name={optionList.name}
value={value}
onChange={updateValue}
>
{optionList.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{optionList.buttonLabel}</button>
</>
);
}
This component accepts to props; optionList and onSelected
optionList is the list of options to render
onSelected is a method that we call when user select and option
On main component, we should change the select section with our select component with props optionList and onSelected
return (
<div>
{selectMenus.map((select) => (
<div key={select.id} className="select-container">
<SelectComponent optionList={select} onSelected={updateValue} />
</div>
))}
</div>
);
So overall code is like this:
import { useState } from "react";
import { v4 as uuid } from "uuid";
export default function App() {
const [url, setUrl] = useState();
const updateValue = (value) => {
setUrl(value);
};
const selectMenus = [
{
id: 1,
label: "Menu 1",
name: "menu1",
buttonLabel: "Menu 1",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
},
{
id: 2,
label: "Menu 2",
name: "menu2",
buttonLabel: "Menu 2",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
},
{
id: 3,
label: "Menu 3",
name: "menu3",
buttonLabel: "Menu 3",
options: [
{
text: "option 1",
value: "option1"
},
{
text: "option 2",
value: "option2"
},
{
text: "option 3",
value: "option3"
}
]
}
];
return (
<div className="App">
<h1>URL Value: {url}</h1>
{selectMenus.map((select) => (
<div key={select.id} className="select-container">
<SelectComponent optionList={select} onSelected={updateValue} />
</div>
))}
</div>
);
}
function SelectComponent({ optionList, onSelected }) {
const [value, setValue] = useState();
const updateValue = ({ target }) => {
setValue(target.value);
if (onSelected) onSelected(target.value);
};
return (
<>
<label htmlFor={optionList.id}>{optionList.label}</label>
<select
id={optionList.id}
name={optionList.name}
value={value}
onChange={updateValue}
>
{optionList.options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
<button>{optionList.buttonLabel}</button>
</>
);
}
Working example is overhere codesandbox
I am working on ReactJS, I created a component using Material UI Autocomplete in which I need to filter the result based on the selections. As you see the object has "GROUP", once the user select any options I need to remove the entire group out the display list. If I select Region or Asia (Region) I need to filter all the objects which has GROUP "RG" and bring back the filtered object once I remove the selected value. Thanks in advance.
const Typeahead = props => {
const classes = useStyles();
let Dictionary = React.useState([]);
const MainDictionary = [
{ NAME: "Region", FIELD: "RG" , GROUP: "RG"},
{ NAME: "Asia (Region)", FIELD: "RG-Asia" , GROUP: "RG"},
{ NAME: "Australia (Region)", FIELD: "RG-Australia" , GROUP: "RG"},
{ NAME: "Central America (Region)", FIELD: "RG-Central America" , GROUP: "RG"},
{ NAME: "Europe (Region)", FIELD: "RG-Eastern Europe" , GROUP: "RG"},
{ NAME: "Country", FIELD: "CY" , GROUP: "CY"},
{ NAME: "Country 1 (Country)", FIELD: "SC-Country 1" , GROUP: "CY"},
{ NAME: "Country 2 (Country)", FIELD: "SC-Country 2" , GROUP: "CY"},
{ NAME: "Country 3 (Country)", FIELD: "SC-Country 3" , GROUP: "CY"},
{ NAME: "Country 4 (Country)", FIELD: "SC-Country 4" , GROUP: "CY"},
{ NAME: "Country 5 (Country)", FIELD: "SC-Country 5" , GROUP: "CY"}
];
Dictionary = MainDictionary;
function filterOptions(event, params) {
Dictionary = MainDictionary;
params.forEach(element => {
Dictionary = Dictionary.filter(b => {
return b.GROUP !== element.GROUP;
}).map(a => {
return a;
});
});
}
return (
<div className={classes.root}>
<Autocomplete
multiple
id="tags-standard"
width="auto"
options={Dictionary}
getOptionLabel={option => option.NAME}
onChange={(event, newValue) => {
filterOptions(event, newValue);
}}
value = {selectedValue}
renderInput={params => (
<TextField
{...params}
variant="standard"
placeholder="Select From Dictionary"
fullWidth
/>
)}
renderOption={(option, { inputValue }) => {
const matches = match(option.NAME, inputValue);
const parts = parse(option.NAME, matches);
return (
<div>
{parts.map((part, index) => (
<span
key={index}
style={{ color: part.highlight? "#36a5f7": "" , fontWeight: part.highlight ? 700 : 400 }}
>
{part.text}
</span>
))}
</div>
);
}}
/>
</div>
);
};
I have an array of countries
const countries = [{
name: 'United States', value: 'US', currency: 'USD'
}, {
name: 'Israle', value: 'IL', currency: 'ILS'
}, {
name: 'United Kingdom', value: 'UK', currency: 'GBP'
}]
And following code in react component
handleCountryChange(val){
console.log(val)
}
<select className="form-control input-lg" name="country" placeholder="Country" >
{ countries.map((val, index) => {
return(<option value={val.value} onClick={() => this.handleCountryChange(val)} key={index}>{val.name}</option>)
})}
</select>
but here my onClick is not being called... I want to get all the fields of the array inside the onClick function... How do I do it either with javascript or reactjs?
And onChange gives the event and targeted value not all the fields
You should put the handler on select element. Not on individual option.
Try the following..
<select className="form-control input-lg" name="country" placeholder="Country" onChange={(event) => this.handleCountryChange(event)}>
{ countries.map((val, index) => {
return(<option value={val.value} key={index}>{val.name}</option>)
})}
</select>
I made it by setting value as a index and then get the element by indexed value from the array
handleCountryChange(e){
this.setState({
country: countries[e.target.value].value,
currency: countries[e.target.value].currency
})
}
<select className="form-control input-lg" name="country" onChange={(e) => this.handleCountryChange(e)}>
{ countries.map((val, index) => {
return(<option value={index} key={index}>{val.name}</option>)
})}
</select>
Put the onChange handler on the select element instead.
Example
class App extends React.Component {
state = {
countries: [
{
name: "United States",
value: "US",
currency: "USD"
},
{
name: "Israle",
value: "IL",
currency: "ILS"
},
{
name: "United Kingdom",
value: "UK",
currency: "GBP"
}
]
};
handleCountryChange = event => {
const { value } = event.target;
const option = this.state.countries.find(
country => country.value === value
);
console.log(option);
};
render() {
const { countries } = this.state;
return (
<select
className="form-control input-lg"
name="country"
placeholder="Country"
onChange={this.handleCountryChange}
>
{countries.map((val, index) => {
return (
<option value={val.value} key={index}>
{val.name}
</option>
);
})}
</select>
);
}
}