mpartan
mpartan

Reputation: 1316

Best way for a React and HTML Select-component to return String instead of Integer

I have a React-class (JSX) that contains following (slightly simplified here) code:

var Select = React.createClass({
  onChange: function (ev) {
     console.log(ev.target.value);
  },
  render: function() {
     var optionsHtml = this.state.options.map(function (el) {
                    console.log(this.props.getValue(el);
                    return (
                        <option key={this.props.getValue(el)}
                                value={this.props.getValue(el)}> { this.props.getLabel(el) } 
                        </option>
                    )
                });
    return <select onChange={this.onChange}>
     {optionsHtml}
    </html>
}

In the render-function, console.log returns Integers for values (i.e. 1, 2, 3) when initializing the Options-HTML and setting the values, however inside the onChange-method value is a String (i.e. "1", "2", "3") when the actual Select-box value is changed.

One way to fix this would be to check and cast the value to Number before using it inside onChange, but is there any other way to do it?

EDIT:

Options-array could look something like this

var options = [
  { id: 1, name: "Test" },
  { id: 2, name: "Test2" },
  { id: 3, name: "Test3" }
]

Component then could be called with getValue and getLabel -functions like this:

<Select options={options}, 
   getValue: function(v) {
      return v.id;
   },
   getLabel: function(v) {
      return v.name;
   }/>

Different type is an issue once I generate a JSON that I'm sending to backend, and I need to the conversion at some point.

Upvotes: 1

Views: 4186

Answers (2)

Andreyco
Andreyco

Reputation: 22872

I would change render method and event listener to this:

onChange(event) {
  const el = this.state.options[event.target.value];
  const value = this.props.getValue(el);
},

render() {
  const options = this.state.options.map((el, idx) => (
    <option key={this.props.getValue(el)} value={idx}>{ this.props.getLabel(e) }</option>
  ));

  return (
    <select onChange={this.onChange}>
      { options }
    </select>
  )
}

Doing this, you are not getting actual value. You are telling "Pick object at index N from within predefined objects and get it's value."

Upvotes: 1

Nick Zuber
Nick Zuber

Reputation: 5637

When your onChange function executes and attempts to read the value of an option tag, it's important to remember that all attributes will be read as strings.

With that being said, note that

onChange: function (ev) {
   console.log(ev.target.value);
   //          ^^^^^^^^^^^^^^^ always string
}

So each time you want to handle a value in your onChange function, you must cast the value to an number. Something like this should do the trick:

onChange: function (ev) {
   var valueInt = parseInt(en.target.value, 10);
   console.log(valueInt);
}

Or if the value isn't necessarily going to be a number, you can attempt to parse it as a number if applicable:

onChange: function (ev) {
   var valueInt;
   try{
       valueInt = parseInt(en.target.value, 10);
   }catch(e){ 
        // handle value not being a number if unexpected
   }
   console.log(valueInt);
}

Upvotes: 5

Related Questions