Get value of select menus when clicking reset button React - javascript

I have a set of select menus and I need to find out the values for all of them when I reset them using reset buttons.
The problem is this only works on change event for options and I can't make it work on reset buttons on the first click as it doesn't detect the change.
Code sample here:
https://stackblitz.com/edit/react-rmp8kf
import React from 'react';
import { useState } from 'react';
import uuid from 'react-uuid';
export default function Select() {
const [value, setValue] = useState({
select1: '',
select2: '',
});
const selectOptions = [
{
options: [
{
text: 'All',
value: '0',
},
{
text: 'Blue',
value: '1',
},
{
text: 'Yellow',
value: '2',
},
{
text: 'Green',
value: '3',
},
],
},
{
options: [
{
text: 'All',
value: '0',
},
{
text: 'Black',
value: '1',
},
{
text: 'White',
value: '2',
},
],
},
];
const handleOnChange = (e) => {
const valueSelected = e.target.value;
setValue({
...value,
[e.target.name]: valueSelected,
});
printAllSelectValues();
};
const resetAllSelections = (e) => {
e.preventDefault();
setValue({
select1: '',
select2: '',
});
printAllSelectValues();
};
const resetSelection = (e) => {
e.preventDefault();
setValue({
...value,
[e.target.dataset.selectName]: '',
});
printAllSelectValues();
};
const printAllSelectValues = () => {
const selectMenus = document.querySelectorAll('select');
selectMenus.forEach((select) =>
console.log(select.name + '=' + select.value)
);
};
return (
<form>
<div>
<label>
<select
name="select1"
value={value.select1}
onChange={handleOnChange}
>
{selectOptions[0].options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
</label>
<button data-select-name="select1" onClick={resetSelection}>
Reset
</button>
</div>
<div>
<label>
<select
name="select2"
value={value.select2}
onChange={handleOnChange}
>
{selectOptions[1].options.map((option) => (
<option value={option.value} key={uuid()}>
{option.text}
</option>
))}
</select>
</label>
<button data-select-name="select2" onClick={resetSelection}>
Reset
</button>
</div>
<button onClick={resetAllSelections}>Reset All</button>
</form>
);
}

The stackblitz sandbox you linked seems to do exactly what you need to. You are getting both values correctly when:
You select any value in any of the 2 select elements
You reset any of the select values individually by using the reset button on the side of each select element
You reset both values at once by using the "Reset All" button
What is the problem? Do you want to get the updated values ?
UPDATE
Okey. So react has the nature that every state update is async, meaning that you need to wait for a state update to happen to use its updated values. Now, you cannot use promises or async/await to do this because react is built intentionally this way and gives you the tools to do so. So you need to use the useEffect hook for this.
https://stackblitz.com/edit/react-bekzpz
Note: worth mentioning that you don't need to grab the data from the HTML elements but in case you want to manipulate DOM elements in react, you are not supposed to do it using the document but by using the useRef hook

Related

Using react-select with multiple inputs

I have multiple react-select inputs, each have their own separate options array. The issue i'm having is I'm now sure how to properly store the output of each select input.
I want to use this select output to POST to my backend but i'm unsure how to do it all with a single handler function.
This is what I have so far, i have 2 paragraphs to just output the appropriate result from the select fields but i can't seem to get it working.
This is the codesandbox i have:
https://codesandbox.io/s/busy-yonath-rlj9e?file=/src/App.js
In your code you are using the useState() hook and everytime a user selects an option, you are setting your state variable to the selected value.
The problem is that everytime you run the setSelectOptions({ e }) function, you are overwriting the existing data with the value of 'e'.
What you can do is:
Create a selectHandler function that takes in 2 arguments (the new value and the value it corresponds to in the state variable)
The code will look something like this:
import "./styles.css";
import Select from "react-select";
import { useEffect, useState } from "react";
export default function App() {
const [selectOptions, setSelectOptions] = useState({
brand: "",
model: "",
color: "",
bodyType: "",
fuelType: "",
transmission: "",
location: ""
});
const brandOptions = [
{ value: "bmw", label: "Bmw" },
{ value: "audi", label: "Audi" },
{ value: "toyota", label: "Toyota" },
{ value: "nissan", label: "Nissan" }
];
const transmissionOptions = [
{ value: "automatic", label: "Automatic" },
{ value: "manual", label: "Manual" }
];
useEffect(() => console.log(selectOptions), [selectOptions])
const handleChange = (e, type) => {
setSelectOptions((previousState) => ({
...previousState,
[type]: e.value,
}));
};
return (
<div className="App">
selected brand: {selectOptions.brand}
<br />
selected transmission:{selectOptions.transmission}
<div className="mb-2" style={{ width: "40%", margin: "0 auto" }}>
<Select
value={selectOptions.brand}
onChange={(e) => handleChange(e, "brand")}
placeholder="Select brand"
options={brandOptions}
/>
<Select
value={selectOptions.transmission}
onChange={(e) => handleChange(e, "transmission")}
placeholder="Select transmission"
options={transmissionOptions}
/>
</div>
</div>
);
}
Just as an explanation, all I am doing in the setSelectOptions() function is passing in the previous values of the state variable and updating the value coinciding to the select field.
Note: Insert this code into your project, I ran it and it worked so let me know if it did help!

Passing value to state using react-select

I'm new to react and trying to learn on my own. I started using react-select to create a dropdown on a form and now I'm trying to pass the value of the option selected. My state looks like this.
this.state = {
part_id: "",
failure: ""
};
Then in my render
const {
part_id,
failure
} = this.state;
My form looks has 2 fields
<FormGroup>
<Label for="failure">Failure</Label>
<Input
type="text"
name="failure"
placeholder="Failure"
value={failure}
onChange={this.changeHandler}
required
/>
</FormGroup>
<FormGroup>
<Label for="part_id">Part</Label>
<Select
name="part_id"
value={part_id}
onChange={this.changeHandler}
options={option}
/>
</FormGroup>
the changeHandler looks like this
changeHandler = e => {
this.setState({ [e.target.name]: e.target.value });
};
The change handler works fine for the input but the Select throws error saying cannot read property name. I went through the API docs and came up with something like this for the Select onChange
onChange={part_id => this.setState({ part_id })}
which sets the part_id as a label, value pair. Is there a way to get just the value? and also how would I implement the same with multiselect?
The return of react-select onChange event and the value props both have the type as below
event / value:
null | {value: string, label: string} | Array<{value: string, label: string}>
So what the error means is that you can't find an attribute of null (not selected), or any attributes naming as name (you need value or label)
For multiple selections, it returns the sub-list of options.
You can find the related info in their document
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' },
];
Update
For your situation (single selection)
option having type as above
const option = [
{value: '1', label: 'name1'},
{value: '2', label: 'name2'}
]
state save selected value as id
changeHandler = e => {
this.setState({ part_id: e ? e.value : '' });
};
pick selected option item via saved id
<Select
name="part_id"
value={option.find(item => item.value === part_id)}
onChange={this.changeHandler}
options={option}
/>
For multiple selections
state save as id array
changeHandler = e => {
this.setState({ part_id: e ? e.map(x => x.value) : [] });
};
pick via filter
<Select
isMulti // Add this props with value true
name="part_id"
value={option.filter(item => part_id.includes(item.value))}
onChange={this.changeHandler}
options={option}
/>
onChange function is a bit different in react-select
It passes array of selected values, you may get first one like
onChange={([selected]) => {
// React Select return object instead of value for selection
// return { value: selected };
setValue(selected)
}}
I have tried the above solutions but some of these solutions does update the state but it doesn't gets rendered on the Select value instantly.
Herewith a demo example:
this.state = {
part_id: null,
};
handleUpdate = (part_id) => {
this.setState({ part_id: part_id.value }, () =>
console.log(`Option selected:`, this.state.part_id)
);
};
const priceOptions = [
{ value: '999', label: 'Item One' },
{ value: '32.5', label: 'Item Two' },
{ value: '478', label: 'Item Three' }
]
<Select
onChange={this.handleUpdate}
value={priceOptions.find(item => item.value === part_id)}
options={priceOptions}
placeholder={<div>Select option</div>}
/>

How to use onChange method in semantic react dropdown

Can someone help me out how to use onChange in dropdown (Semantic UI React). I am reading the docs, but still, I don't get it. It does have onChange props.
onChange(event: SyntheticEvent, data: object)
How do I use it? Like, I have method dropdownmethod().
edit - implemented the suggestion, but it didn't work. I think in your suggestion, you didn't bind the function. But, I bind the function.
onChangeFollower(event,data){
console.log("on change follower",data.text)
}
render() {
console.log("this.props",this.props)
var onChangeFollower = this.onChangeFollower.bind(this)
return (
<div>
<h2>project settings are here</h2>
<h2>Add new Member</h2>
<Dropdown onChange={onChangeFollower}
placeholder='Select Member'
fluid search selection options={arr} />
<h2>List of members</h2>
{lr}
</div>
As stated in the docs, you just need to pass a reference of your method and then you will get 2 parameters:
The native event
The object of the option selected
Here is a running example
Here is a code snippet (it uses a CDN but throws some debug warnings, so ignore them)
const { Dropdown } = semanticUIReact;
const languageOptions = [
{ key: 'eng', text: 'English', value: 'eng' },
{ key: 'spn', text: 'Spanish', value: 'spn' },
{ key: 'rus', text: 'Russian', value: 'Russian' },
]
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
searchQuery: '',
selected: null
}
}
onChange = (e, data) => {
console.log(data.value);
this.setState({ selected: data.value });
}
onSearchChange = (e, data) => {
console.log(data.searchQuery);
this.setState({ searchQuery: data.searchQuery });
}
render() {
const { searchQuery, selected } = this.state;
return (
<div>
<Dropdown
button
className='icon'
fluid
labeled
icon='world'
options={languageOptions}
search
text={searchQuery}
searchQuery={searchQuery}
value={selected}
onChange={this.onChange}
onSearchChange={this.onSearchChange}
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.9/semantic.min.css"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/semantic-ui-react#0.77.1/dist/umd/semantic-ui-react.min.js"></script>
<div id="root"></div>
Edit
As a followup to your comment.
I checked example. Even there when i type something, it doesnt show me
anything in console
You are not talking about onChange of the select you are talking about when the search input has changed.
You can use onSearchChange with same parameters. (I've updated the example)
I have implemented as below
React hooks function is as below , if you prefer you can pass handleOnChange as a prop as well
const RenderDropdown = ({optionsArray}) => {
const handleOnChange = (e, data) => {
console.log(data.value);
}
return (
<Dropdown
placeholder='Please select'
fluid
selection
options={optionsArray}
onChange={handleOnChange}
/>
);
}
options array as below
const optionsArray = [
{
key: 'male',
text: 'Male',
value: 'male',
image: { avatar: true, src: 'https://semantic-ui.com/images/avatar/small/elliot.jpg' },
},
{
key: 'female',
text: 'Female',
value: 'female',
image: { avatar: true, src: 'https://semantic-ui.com/images/avatar/small/stevie.jpg' },
}
]
use onChange event to detect the changes in the dropdown list
onSearchChange={(e, v) => {
changeMethod(e, v)
}}
use onSearchChange event to detect the search input
onSearchChange={(e, v) => {
searchMethod(e, v)
}}
and you have to define searchMethod and changeMethod as consts in the top of your page.
Below is the working code of your's:
onChangeFollower(event, data){
console.log("on change follower",data.text)
}
render() {
console.log("this.props",this.props)
return (
<div>
<h2>project settings are here</h2>
<h2>Add new Member</h2>
<Dropdown onChange={this.onChangeFollower}
placeholder='Select Member'
fluid search selection options={arr} />
<h2>List of members</h2>
{lr}
</div>
)
}

ReactJs Select add default value

I want to store select default value if user not touch it in ReactJs. How is that possible?
<select onChange={this.valSelected.bind(this)}>
{currencies.map(function(name, index){
return <option value={name}>{name}</option>;
})}
</select>
and
valSelected(event){
this.setState({
valSelected: event.target.value
});
}
You can just add a value property to the select element, set by your state.
<select value={this.state.valSelected} onChange={this.valSelected.bind(this)}>
{currencies.map(function(name, index){
return <option value={name}>{name}</option>;
})}
</select>
This is described here in the react docs: Doc Link
Then set a default state for the component, either in the constructor or with getInitialState: What is the difference between using constructor vs getInitialState in React / React Native?
Use defaultValue to select the default value.
const statusOptions = [
{ value: 1, label: 'Publish' },
{ value: 0, label: 'Unpublish' }
];
const [statusValue, setStatusValue] = useState('');
const handleStatusChange = e => {
setStatusValue(e.value);
}
return(
<>
<Select options={statusOptions} defaultValue={[{ value: published, label: published == 1 ? 'Publish' : 'Unpublish' }]} onChange={handleStatusChange} value={statusOptions.find(obj => obj.value === statusValue)} required />
</>
)

How do I create a dynamic drop down list with react-bootstrap

The example code in the react-bootstrap site shows the following. I need to drive the options using an array, but I'm having trouble finding examples that will compile.
<Input type="select" label="Multiple Select" multiple>
<option value="select">select (multiple)</option>
<option value="other">...</option>
</Input>
You can start with these two functions. The first will create your select options dynamically based on the props passed to the page. If they are mapped to the state then the select will recreate itself.
createSelectItems() {
let items = [];
for (let i = 0; i <= this.props.maxValue; i++) {
items.push(<option key={i} value={i}>{i}</option>);
//here I will be creating my options dynamically based on
//what props are currently passed to the parent component
}
return items;
}
onDropdownSelected(e) {
console.log("THE VAL", e.target.value);
//here you will see the current selected value of the select input
}
Then you will have this block of code inside render. You will pass a function reference to the onChange prop and everytime onChange is called the selected object will bind with that function automatically. And instead of manually writing your options you will just call the createSelectItems() function which will build and return your options based on some constraints (which can change).
<Input type="select" onChange={this.onDropdownSelected} label="Multiple Select" multiple>
{this.createSelectItems()}
</Input>
My working example
this.countryData = [
{ value: 'USA', name: 'USA' },
{ value: 'CANADA', name: 'CANADA' }
];
<select name="country" value={this.state.data.country}>
{this.countryData.map((e, key) => {
return <option key={key} value={e.value}>{e.name}</option>;
})}
</select>
bind dynamic drop using arrow function.
class BindDropDown extends React.Component {
constructor(props) {
super(props);
this.state = {
values: [
{ name: 'One', id: 1 },
{ name: 'Two', id: 2 },
{ name: 'Three', id: 3 },
{ name: 'four', id: 4 }
]
};
}
render() {
let optionTemplate = this.state.values.map(v => (
<option value={v.id}>{v.name}</option>
));
return (
<label>
Pick your favorite Number:
<select value={this.state.value} onChange={this.handleChange}>
{optionTemplate}
</select>
</label>
);
}
}
ReactDOM.render(
<BindDropDown />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
// on component load, load this list of values
// or we can get this details from api call also
const animalsList = [
{
id: 1,
value: 'Tiger'
}, {
id: 2,
value: 'Lion'
}, {
id: 3,
value: 'Dog'
}, {
id: 4,
value: 'Cat'
}
];
// generage select dropdown option list dynamically
function Options({ options }) {
return (
options.map(option =>
<option key={option.id} value={option.value}>
{option.value}
</option>)
);
}
<select
name="animal"
className="form-control">
<Options options={animalsList} />
</select>
Basically all you need to do, is to map array. This will return a list of <option> elements, which you can place inside form to render.
array.map((element, index) => <option key={index}>{element}</option>)
Complete function component, that renders <option>s from array saved in component's state. Multiple property let's you CTRL-click many elements to select. Remove it, if you want dropdown menu.
import React, { useState } from "react";
const ExampleComponent = () => {
const [options, setOptions] = useState(["option 1", "option 2", "option 3"]);
return (
<form>
<select multiple>
{ options.map((element, index) => <option key={index}>{element}</option>) }
</select>
<button>Add</button>
</form>
);
}
component with multiple select
Working example: https://codesandbox.io/s/blue-moon-rt6k6?file=/src/App.js
A 1 liner would be:
import * as YourTypes from 'Constants/YourTypes';
....
<Input ...>
{Object.keys(YourTypes).map((t,i) => <option key={i} value={t}>{t}</option>)}
</Input>
Assuming you store the list constants in a separate file (and you should, unless they're downloaded from a web service):
# YourTypes.js
export const MY_TYPE_1="My Type 1"
....
You need to add key for mapping otherwise it throws warning because each props should have a unique key. Code revised below:
let optionTemplate = this.state.values.map(
(v, index) => (<option key={index} value={v.id}>{v.name}</option>)
);
You can create dynamic select options by map()
Example code
return (
<select className="form-control"
value={this.state.value}
onChange={event => this.setState({selectedMsgTemplate: event.target.value})}>
{
templates.map(msgTemplate => {
return (
<option key={msgTemplate.id} value={msgTemplate.text}>
Select one...
</option>
)
})
}
</select>
)
</label>
);
I was able to do this using Typeahead. It looks bit lengthy for a simple scenario but I'm posting this as it will be helpful for someone.
First I have created a component so that it is reusable.
interface DynamicSelectProps {
readonly id: string
readonly options: any[]
readonly defaultValue: string | null
readonly disabled: boolean
onSelectItem(item: any): any
children?:React.ReactNode
}
export default function DynamicSelect({id, options, defaultValue, onSelectItem, disabled}: DynamicSelectProps) {
const [selection, setSelection] = useState<any[]>([]);
return <>
<Typeahead
labelKey={option => `${option.key}`}
id={id}
onChange={selected => {
setSelection(selected)
onSelectItem(selected)
}}
options={options}
defaultInputValue={defaultValue || ""}
placeholder="Search"
selected={selection}
disabled={disabled}
/>
</>
}
Callback function
function onSelection(selection: any) {
console.log(selection)
//handle selection
}
Usage
<div className="form-group">
<DynamicSelect
options={array.map(item => <option key={item} value={item}>{item}</option>)}
id="search-typeahead"
defaultValue={<default-value>}
disabled={false}
onSelectItem={onSelection}>
</DynamicSelect>
</div>

Categories