Get selected option text using react js? - javascript

I have my select list component rendering my select list:
<form className="pure-form">
<select ref="selectMark" className="mark-selector"
onChange={this.onChange}>{this.getOptions()}
</select>
</form>
I have a method on the component to create the options:
getOptions: function () {
return this.props.renderProps.data.map(function (item) {
return <option key={item.value} value={item.value}>{item.label}</option>;
}.bind(this));
},
My onChange method works fine with the value:
onChange: function(event) {
var newValue = event.nativeEvent.target.value;
this.props.renderProps.onSaveCare(newValue);
this.setState({value: newValue});
this.toggleEdit();
},
Is there a way I can get the option text? This gives me undefined
event.nativeEvent.target.text; //undefined

Something like this should do
var index = event.nativeEvent.target.selectedIndex;
event.nativeEvent.target[index].text
Here is a demo http://jsbin.com/vumune/4/

You can get the option text by replacing this:
event.nativeEvent.target.text;
with this:
event.target.options[event.target.selectedIndex].text

If it's single select, here is more simple way:
e.target.selectedOptions[0].text

This worked for me
const {options, value} = e.target;
console.log(options[value].innerHTML);
Edit: I just realized I was using the "value" field to store the ID of some objects, from 0 to n. I guess a better approach could be the following:
const {options, selectedIndex} = e.target;
console.log(options[selectedIndex].innerHTML);

The text of an option is simply the label property of the corresponding item.
In your case, to retrieve the text of the selected option, you can do:
var selectedItem = this.props.renderProps.data.find(function (item) {
return item.value === event.target.value;
});
selectedItem.label;
Array.prototype.find is part of the ES6 proposal. Underscore or lodash already package it as the _.find method.

Here what i do to retrieve the text from select option in react js.
this.refs.selectMark[this.refs.selectMark.value].text

It's easy using refs.
import the hook
import React, { useContext, useState, useEffect, useRef } from "react";
instantiate it
const yourNewRef= useRef();
Reference it in your element
ref={yourNewRef}
Then you can access it in any event or function by simply calling:
let textSelectOption = yourNewRef.current.options[yourNewRef.current.selectedIndex].text
You can access the value simply by calling
let optionValue = yourNewRef.current.value
refs are great, you can do almost everything you would using jQuery.
Take a look at yourNewRef on console and access all the content via the .current property

2020 and this Worked For Me
My Select Element :
<FormGroup>
{<Select
closeMenuOnSelect={true}
components={animatedComponents}
options={Options}
value = "Ahmedabad"
onChange={this.handleChange}
name = "citySelect"
/>}
</FormGroup>
Call handler :
handleChange = (e) => {
console.log(e.value)
}

change your menu item accordingly
Current / Temporary address
Permanent address
Office / Business Address
and on change event get
onChange = {(e,index) =>
( setAddressChangeType(e.target.value), console.log(index.props.id) )
}

make your dropdown accordingly and get value on change event like
onChange = {(e,index) =>
( setAddressChangeType(e.target.value), console.log(index.props.id) )
}

Related

React <select> automatic change does not trigger onChange

In my page, I have two <select> elements, where the options of the second one depends on the value of the first one.
In this case, the "problem" is that the options for a certain value in the first select are different from the options given when the first select has another value. Basically:
Alfa Romeo
Giulietta
Mito
Porsche
Cayenne
911
I've created a simple fiddle just to show you the example, and the problem: https://codesandbox.io/s/select-autochange-7bfj6
Please, open the console to see what I'm talking about. So, basically, at start 'Porsche' and '911' are selected. Then, if I change '911' to 'Cayenne' everything is good.
The problem is when I change 'Porsche' to 'Alfa': as it should be, the second select changes its value to 'Giulietta', BUT the onChange event of the second select is not triggered.
I'm mostly sure that the problem is some kind of de-synchronization between UI and state: in the state, the secondselect still has the value '911', but since that option is no longer available in the second select, it autoselect the first possible value.. But that autoselection is just "graphical".
I know this could be fixed by adding a "null" value in the second select, with the option <option value={''} label={'Select a Model'} />. But I'd like to mantain the autoselection when the first select changes.
EDIT: actually, the fix I proposed is not an actual fix: that 'select a Model' options has the value '', but the handleSelectSelectChange is still not triggered, so, while the UI selected value is '', in the state I still have '911'
React.useEffect(()=> {
if (!secondOptionsMemoized.some(x=> x === secondSelectValue)) {
console.log('Second Select Change in useEffect');
setSecondSelectValue(secondOptionsMemoized[0]);
}
}, [secondSelectValue, secondOptionsMemoized]);
You can use useEffect instead of useMemo and another state which set the second options:
import React, { useEffect } from "react";
import "./styles.css";
export default function App() {
const alfaForSecondOptions = ["Giulietta", "Mito"];
const otherForSecondOptions = ["Cayenne", "911"];
const [firstSelectValue, setFirstSelectValue] = React.useState("Porsche");
const [secondSelectValue, setSecondSelectValue] = React.useState("911");
const [secondOptions, setSecondOptions] = React.useState(
otherForSecondOptions
);
useEffect(() => {
console.log(secondSelectValue);
}, [secondOptions]);
useEffect(() => {
if (firstSelectValue === "Alfa") {
setSecondOptions(alfaForSecondOptions);
setSecondSelectValue("Giulietta");
} else {
setSecondOptions(otherForSecondOptions);
setSecondSelectValue("911");
}
}, [firstSelectValue]);
const handleFirstSelectChange = (e) => {
console.log("First Select Change", e.target.value);
setFirstSelectValue(e.target.value);
};
const handleSecondSelectChange = (e) => {
console.log("Second Select Change", e.target.value);
setSecondSelectValue(e.target.value);
};
return (
<div className="App">
<label>
<p>Brand</p>
<select onChange={handleFirstSelectChange} value={firstSelectValue}>
<option value={"Alfa"} label={"Alfa"} />
<option value={"Porsche"} label={"Porsche"} />
</select>
</label>
<label>
<p>Model</p>
<select onChange={handleSecondSelectChange} value={secondSelectValue}>
{secondOptions.map((x) => {
return <option key={x} value={x} label={x} />;
})}
</select>
</label>
</div>
);
}

Selected drop down value is not being updated in the drop down menu in React when there is a function call in onChange()

I am working on a filter that will fetch the data from serviceNow depending on what the user has selected in the drop down menu. In my onChange(), I have a function call that will be filtering the data based on the value returned by onChange(). However, as soon as I put the function call(handleFilter()), the result is correctly fetched and displayed but the drop down menu selection is not updated.
Here is my drop down menu snippet
export default function DropDownComponent(props) {
return (
<div className="DropDownBox">
<Select
defaultValue={props.options[0]}
isSearchable={false}
name="DropDownBox"
options={props.options}
styles={dropDownStyles}
autosize={false}
onChange = {
val => {
props.changeDropdownValue(val);
props.handleFilter(val)
}
}
/>
<div className="caret_down_centered" />
</div>
);
props.handleFilter(val) is the function call that prevents the updated in the drop down. If I remove this, then the drop down selection is updated but the whole functionality is rendered useless because there is no filtering being done.
handleFilter(val) is a parent class method & is simply invoking different API's depending upon what the value of val is which is passed from onChange(). I have no idea why it is interfering with the drop down menu.
I read that we can use a state and update the state everytime there is a change in selection but since I have a functional component, I am not sure how that will go.
I was not sure if handleFilter() code is needed here since it is a long code but if needed, then please let me know. I will post it here.
Try this:
const DropDownComponent = props => {
return (
<select
name="selectFieldName"
value={props.value}
onChange={props.handleChange}
// rest...
>
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
</select>
)
}
class Parent extends React.Component {
// initial setup
constructor(props) {
super(props)
this.state = {
value: 2 // Set your default value
}
}
handleFilter = (value) => {
// Here you fetch the data using 'value' argument
console.log(value)
}
handleChange = e => {
const value = e.target.value
// update value
this.setState({
value // no need to write 'value' because both have the same name
})
// Call handleFilter passing selected "value"
this.handleFilter(value)
}
render() {
return (
<div>
{/* Passing value and handleChange */}
<DropDownComponent
value={this.state.value}
handleChange={this.handleChange}
/>
<p>Value {this.state.value}</p>
</div>
)
}
}
ReactDOM.render( <Parent / > , document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.2/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.2/react-dom.min.js"></script>
<div id="root"></div>
I guess your problem is calling handleFilter method in wrong place. Also, you didn't tell how you have set the selected value inside the handleFilter method. See this codeSandbox for example.

React-Select trigger selection of option

I have a react component with a <Select options={myoptions} onChange={this.mychangehandler}/> element from react-select. I have saved some settings using redux that can be accessed e.g. using this.props.myreducer.dropdownvalue(already tested, the values are available when first rendering the component)
Depending on the redux props I want to automatically select one of the options in the dropdown. How can I tell the <Select.../>dropdown to automatically select option 2 if this.props.myreducer.dropdownvalue is equal to 1?
There are countless properties but somehow I found no one that can help me automatically select the proper entry.
Any ideas? Solutions that will automatically trigger onChange as well prefered, but should be no problem if not.
Thanks in advance :)
Regards Christian
edit: Here is the full code:
import React, {Component} from 'react';
import { connect } from 'react-redux';
import Auxiliary from '../../../../../../../hoc/Auxiliary/Auxiliary';
import classes from './Dropdown.module.css';
import Select from 'react-select';
class Dropdown extends Component {
changeSetting = (event) => {
console.log('qid'+this.props.qid)
console.log('event: '+JSON.stringify(event))
if(this.props.certs.certquestions[this.props.qid].red === event.id)
{
this.props.colorchanger("red")
}else if(this.props.certs.certquestions[this.props.qid].yellow === event.id)
{
this.props.colorchanger("yellow")
}else if(this.props.certs.certquestions[this.props.qid].green === event.id)
{
this.props.colorchanger("green")
}
}
render(){
const options = []
const qid = this.props.qid
console.log('qid:'+qid)
const question = this.props.certs.certquestions[qid]
const opt = question.options.split("|")
for(let i = 0;i<opt.length;i++){
let optname = opt[i]
options.push({value:i, label:optname, id:i})
}
let notes = "";
let selectedOption = null;
if(this.props.loadp)
{
let progress = this.props.certs.loadedProgress[this.props.users.users[this.props.users.currentuser].target_id+'_'+this.props.q]
if (typeof progress !== 'undefined')
{
notes = progress.notes
selectedOption = progress.selectedOption
}
}
return(
<Auxiliary>
<h3>{question.title}</h3>
<Select className = {classes.Dropdown} options={options} onChange={this.changeSetting}/ value={selectedOption}> //selectedOption is an Integer
<textarea value = {notes}/>
</Auxiliary>
)
}
}
const mapStateToProps = state => {
return {
certs: state.certs,
users: state.users
};
}
export default connect(mapStateToProps, null)(Dropdown);
the options have different labels and value and id from 0 to 9. I tried to add value={selectedOption} to the Select element, also tried it with the label instead, but it always only shows the "Select..." placeholder and doesn't select the option and trigger the onChange. Any idea what I'm doing wrong?
Solved: I now know what I did wrong, thanks a lot :) I needed to pass an object with value, id and label to value :)
I needed to pass an object like this: {"value":0,"label":"v1","id":0} to value

React Select mapping issue

I'm using react-select in my project and I'm using it within a map like that:
renderItems() {
this.props.items.map(item => (
<Select
id="options"
value={this.state.optionSelected}
onChange={this.onChangeOption}
options={this.showOptions()}
/>
);
}
It show correctly all my options for all my items but now I can not get rid about the select...
Basically when I select an option on a single item, that option is changing for all items...
This is what i did so far:
onChangeOption(e) {
this.setState({ optionSelected: e.value });
}
How can I adjust it to change the option only on the one I wish to change it?
Thanks
You are using the same change handler for all of your select components and then set the same state value for all your select components. To deal with this either you need to separate your select components with a container component that handles their own state and change event or you need to give each select component a unique state value.
Example
renderItems() {
this.props.items.map(item => (
<Select
id="options"
value={this.state.optionSelected[item.id]}
onChange={(event) => this.onChangeOption(event, item.id)}
options={this.showOptions()}
/>
);
}
onChangeOption(event, itemId) {
this.setState((prevState) => {
const prevStateClone = Object.assign({}, prevState);
prevStateClone.optionSelected[itemId] = event.target.value;
return prevStateClone;
});
}
Instead of making optionSelected string variable, make it as array in state.
Now do the following.
renderItems() {
this.props.items.map(item, index => (
<Select
id="options"
value={this.state.optionSelected[index]}
onChange={(selectedValue) => this.onChangeOption(selectedValue, index)}
options={this.showOptions()}
/>
);
}
onChangeOption(selectedValue, index) {
const optionSelected = this.state.optionSelected.slice() // slicing to get new copy of optionSelected instead of referencing to old one which causes mutation
optionSelected[index] = selectedValue
this.setState({optionSelected: optionSelected})
}
What you were doing is using a single variable to hold values of the select box. So if anyone changes, it will reflect all select box
Try cloning the object to a new object or if this optionSelected is a class, you can implement a constructor that clones it for your like:
export class optionSelectedClass {
myfield = '';
constructor(fields){
this.myField = fields.myField;
}
}
or even
export class optionSelectedClass {
myfield = '';
constructor(fields){
for (let f in fields) {
if (!this[f]) {
this[f] = fields[f];
}
}
}
}

Materialize inputs not triggering onChange in React?

I have a Materialize input like so:
<input type="date" className="datepicker" onChange={this.props.handleChange} />
It is being correctly initialised by Materialize, but not firing onChange when the value of the datepicker changes. What am I doing wrong here? This problem seems to extend to all Materialize inputs.
On componentDidUpdate() using a prop id
var elem = document.getElementById('date');
M.Datepicker.init(elem,{
onClose:()=>{
this.state.date = elem.value;
this.setState(this.state)
}
});
I'm pretty sure this solves the caveat if you put it in your componentDidMount component.
If the select is to be re-rendered on state change, this should as well be put in componentDidUpdate
// find the select element by its ref
const el = ReactDOM.findDOMNode(this.refs.ref_to_my_select);
// initialize the select
$('select').material_select();
// register a method to fireup whenever the select changes
$(el).on('change', this.handleInputChange)
To get the value of the datepicker in materialize they provide an onSelect option when initialising the component:
var instances = M.Datepicker.init(
elems,
{
onSelect:function(){
date = instances[0].date;
console.log(date);
}
}
);
https://codepen.io/doughballs/pen/dyopgpa
Every time you pick a date, onSelect fires, in this case console.logging the chosen date.
When you close the datepicker (which is actually a modal), that's when the onChange fires, in this case logging 'onChange triggered' to the console.
that's my solution. I use useRef hook, to identify datepicker input and when onClose is fired, we can capture the object and data value, through ref var.
import React, { useEffect, useState, useRef } from "react";
import M from "materialize-css";
export default function App() {
const fromref = useRef(null); //create reference
const [date, setDate] = useState({ fromdate: "" });
const { fromdate } = date;
useEffect(() => {
let elem = document.querySelectorAll(".datepicker");
M.Datepicker.init(elem, {
firstDay: true,
format: "yyyy-mm-dd",
onClose: function() { // when onclose datepicker, we can get the value and data through the ref
console.log(fromref.current.name, fromref.current.value);
setDate({ [fromref.current.name]: fromref.current.value });
}
});
}, []);
return (
<form class="col s12">
<div class="row">
<div class="input-field col s12">
<input
name="fromdate"
type="text"
class="datepicker"
placeholder="from date"
ref={fromref} //set reference to the input
/>
</div>
</div>
</form>
);
}
If you want to get the value or other attributes you can access them from instaces variable when initialized and then check before submitting your form.
var elems = document.querySelectorAll('.timepicker');
var instances = M.Timepicker.init(elems);
Then in order to get your value before submitting your form can do as follow:
var date = instances[0].el.value;
There are two things which might be stopping the execution of expected behaviour.
If the code which you have displayed question section is from
rendered html tree, then onchnage assigment needs to be called while
assignment itself.
<input type="date" className="datepicker" onChange=this.props.handleChange(event)/>
Note: Previously browser events use to expects event callback
handlers in string format as a value.
In MaterializeCss documentation there is no mentioning of onChange event, this means there cannot be direct way to get it.
https://materializecss.com/pickers.html
It looks like you're using materialize directly in your post but if it is possible, you could try using react-materialize as it wraps all the materialize components such that it's easier to use with React. Using react-materialize would probably be the cleanest way to handle state and event changes as they provide a convenience wrapper around each materialize component.
When using the date picker from react-materialize, you'll need to pass the handleChange method into the options prop like so:
<DatePicker
options={{
...,
onSelect: this.props.handleChange
}}
/>
In the case of using the materialize date picker independently, if you could provide more details on how you're initializing the date picker input, I could provide a more relevant answer. But I'll give it a shot in the dark.
From the materialize docs it looks like you'll also have to pass back some options when you initialize it to handle a callback function when a date is selected.
I've added a JSFiddle that has a working example as well as a code snippet below, notice that when you select a date, 'hello world' is logged in the console, and the date is the first argument passed into the callback.
class Datepicker extends React.Component {
constructor(props) {
super(props)
}
handleChange(date) {
console.log('hello world', date);
}
componentDidMount() {
var elems = document.querySelectorAll('.datepicker');
var instances = M.Datepicker.init(elems, {
onSelect: this.handleChange
});
}
render() {
return (
<div>
<input type="text" className="datepicker" />
</div>
)
}
}
Live Example Fiddle
So to answer your question of how to handle events and setting the state, you just need to pass your handleChange method into the provided options configs depending on how you're using materialize date picker. In regards to integrating with a form, you could use the other callback hooks like onClose to do form validation.

Categories