How does one set the default value of an uncontrolled <select> in a JSX stanza? I have many controlled <select>'s in flight, I know the difference.
<select
// defaultValue="Select a type"
// value="Select a type"
onChange={ this.handleTypeSelect.bind(this, event) }
>
<option value="" disabled selected>Select a type</option>
<option value="type1">type1</option>
<option value="type2">type2</option>
</select>
Running the code above as-is generates the dreaded:
Warning: Use the defaultValue or value props on <select> instead of settingselectedon <option>
Removing the selected line and uncommenting the value or defaultValue lines removes the console warning but has no effect in the browser at all (as in the default value does not show up).
What am I missing?
defaultValue takes the value of the default option you want selected. Your option Select a type has no value.
If you do <option value="-1">Select a type</option> then defaultValue={-1} it should work.
<select defaultValue={-1} onChange={ this.handleTypeSelect.bind(this, event)}>
<option value="-1" disabled>Select a type</option>
<option value="type1">type1</option>
<option value="type2">type2</option>
</select>
Related
I've got a <select> in a LiveComponent and I want to react to the value being changed. There's no submit button. I have this:
<form>
<select phx-change="per_page_changed" phx-target={#myself} >
<option value={3}>3</option>
<option value={5}>5</option>
</select>
</form>
When I change the value, my component's handle_event is called, but the params are %{"_target" => ["undefined"]} - no value from the select. What I am I doing wrong?
Add a name attribute
The <select> needs a name attribute, like this:
<form>
<select name="per_page" phx-change="per_page_changed" phx-target={#myself} >
<option value={3}>3</option>
<option value={5}>5</option>
</select>
</form>
Without a name attribute, LiveView doesn't know what key to use for the input value. With name="per_page", the params to handle_event/3 are %{"_target" => ["per_page"], "per_page" => "5"}.
In my code, I want to make it a default selected value if there is only one.
As of now the code looks as follows:
<select
name="something"
value={this.props.parentProps.value}
<option value="" disabled selected>--Select--</option>
<option value="Other">Other</option>
</select>
The idea here is to have the only option selected, if there is only one.
I could copy them out to and array within the code if needed:
<select options={something}
What would you recommend?
Basically I want something like:
if(only one option)
Select(that one);
you can do something like this:
<select
name="something"
value={this.props.parentProps.value}
<option value="" disabled selected={options.length === 1}>--Select--</option>
<option value="Other">Other</option>
</select>
this options.length === 1 will return true or false that will trigger the selected
I am using reactstrap with React JS and trying to figure out how to bind the input dropdown list.
When the data is coming in, the optionID can be from any from 1 to 5. I would expect that
when I bring up the UI, the dropdown is always showing Select option and never the other.
I thought if I set the selected={this.state.optionID === Input.value} it would make it work.
Any help is appreciated. Thanks.
<Input type="select" name="select" id="statusDropDown"
value={this.state.optionID} selected={this.state.optionID === Input.value}
onChange={this.handleOptionChange}>
<option value={0}>Select</option>
<option value={1}>Option 1</option>
<option value={2}>Option 2</option>
<option value={3}>Option 3</option>
<option value={4}>Option 4</option>
<option value={5}>Option 5</option>
</Input>
Please find the working sample here. My suggestion is to use a functional component.
Angular < 1.4 works with ng-options shown as such:
<select ng-options="option.value as option.label for option in options" ng-model="selectedValue">
With the following array of options:
[{ value:"4_220588",label:"dropdown 1-test value 1"},{value:"4_220589",label:"dropdown 1-test value 2"}]
If you look at the resultant HTML is is as you would expect:
<select ng-options="option.value as option.label for option in options" ng-model="selectedValue" class="ng-pristine ng-valid ng-touched">
<option value="" class="">-- SELECT ONE --</option>
<option value="0" label="dropdown 1-test value 1">dropdown 1-test value 1</option>
<option value="1" label="dropdown 1-test value 2">dropdown 1-test value 2</option>
</select>
As soon as you change the angular version to Angular 1.4+, the option value attribute get's messed up. Here is the output with the same ng-options using a newer version of angular:
<select ng-options="option.value as option.label for option in options" ng-model="selectedValue" class="ng-pristine ng-valid ng-empty ng-touched">
<option value="" class="" selected="selected">-- SELECT ONE --</option>
<option label="dropdown 1-test value 1" value="string:4_220588">dropdown 1-test value 1</option>
<option label="dropdown 1-test value 2" value="string:4_220589">dropdown 1-test value 2</option>
</select>
What is the solution to getting the value to show up still as the index of the array?
Here is the plnkr: http://plnkr.co/edit/3CTUI9b9ntTGWhXDNQI5?p=preview
Your application logic should not be sensitive to the value attribute in the dropdown, because ng-model will set the model correctly regardless of what is output in the HTML. If you application logic does expect a specific format for this attribute, you have 3 ways to deal with this breaking change.
Use ng-repeat instead of ng-options. This is the least recommended option, as it changes the way the select lists work significantly.
Use a track by clause to enforce the key format that you are expecting, i.e. option.value as option.label for option in options track by option.value. This presumes that option.value exists and is the value you wish to represent. http://plnkr.co/edit/TSXfkpf1lhsE9QYa2NAc?p=preview
Change your application logic to expect the hashkey instead, or preferably correct the logic so that it only relies upon ng-model.
One solution would be to use ng-repeat over the options.
<select ng-model="vm.selectedValue">
<option value="" selected disabled>-- SELECT ONE --</option>
<option ng-repeat="option in options"
value="$index"
ng-selected="option === vm.selectedValue">
{{option.label}}
</option>
</select>
Here is your updated Plunkr.
This should do the trick:
<select ng-options="index as option.label for (index, option) in options2" ng-model="vm.selectedValue">
<option value="">-- SELECT ONE --</option>
</select>
On render the value of the selected option would be string:index but will output the desired value without the type included. Here is your edited plunker with the expected result in the Selected Value:
Plunker
I've got a very simple form with a select that contains all the states + abbreviations. When using the keyboard to navigate the second keypress doesn't change ng-model value in certain circumstances. For example if you tab to the select element and hit T it will properly select Tennessee and TN will be placed into the ng-model. Hitting down arrow or T a second time updates the displayed value to Texas, but ng-model is still set to TN. Weirdly enough this doesn't occur if its 2 different letters, so T followed by A correctly puts AL into the ng-model.
The HTML looks like this:
<div>
<label for="user_city">City</label>
<input type="text" name="user_city" id="user_city" ng-model="user.city" />
<label for="user_state">State*</label>
<select name="user_state" id="user_state" ng-model="user.state" style="width: 228px" required>
<option value="AL">Alabama</option>
<option value="AK">Alaska</option>
<option value="AZ">Arizona</option>
<option value="AR">Arkansas</option>
<option value="CA">California</option>
<option value="CO">Colorado</option>
<option value="CT">Connecticut</option>
<option value="DE">Delaware</option>
<option value="DC">District Of Columbia</option>
<option value="FL">Florida</option>
<option value="GA">Georgia</option>
<option value="HI">Hawaii</option>
<option value="ID">Idaho</option>
<option value="IL">Illinois</option>
<option value="IN">Indiana</option>
<option value="IA">Iowa</option>
<option value="KS">Kansas</option>
<option value="KY">Kentucky</option>
<option value="LA">Louisiana</option>
<option value="ME">Maine</option>
<option value="MD">Maryland</option>
<option value="MA">Massachusetts</option>
<option value="MI">Michigan</option>
<option value="MN">Minnesota</option>
<option value="MS">Mississippi</option>
<option value="MO">Missouri</option>
<option value="MT">Montana</option>
<option value="NE">Nebraska</option>
<option value="NV">Nevada</option>
<option value="NH">New Hampshire</option>
<option value="NJ">New Jersey</option>
<option value="NM">New Mexico</option>
<option value="NY">New York</option>
<option value="NC">North Carolina</option>
<option value="ND">North Dakota</option>
<option value="OH">Ohio</option>
<option value="OK">Oklahoma</option>
<option value="OR">Oregon</option>
<option value="PA">Pennsylvania</option>
<option value="RI">Rhode Island</option>
<option value="SC">South Carolina</option>
<option value="SD">South Dakota</option>
<option value="TN">Tennessee</option>
<option value="TX">Texas</option>
<option value="UT">Utah</option>
<option value="VT">Vermont</option>
<option value="VA">Virginia</option>
<option value="WA">Washington</option>
<option value="WV">West Virginia</option>
<option value="WI">Wisconsin</option>
<option value="WY">Wyoming</option>
</select>
</div>
Here is a jsfiddle demonstrating the issue: http://jsfiddle.net/cKF6Q/2/
To duplicate, click the city box and then press TAB to focus the select box and type T T. You'll see user.state go to TN on the first press of T, but the second one is ignored.
NOTE: This is only the SECOND keypress so you have to reload the page between tests.
I had the exact same problem. Here's a jsFiddle - the first dropdown has been "fixed", the second one has not (just for demonstration).
<div ng-app>
<input type="text" name="name" ng-model="form.name" />
<select name="expirationMonth" ng-model="form.expirationMonth">
<option value="">--</option>
<option>01</option>
<option>02</option>
<option>03</option>
<option>04</option>
<option>05</option>
<option>06</option>
</select>
<select name="expirationYear" ng-model="form.expirationYear">
<option>2014</option>
<option>2015</option>
<option>2016</option>
<option>2017</option>
</select>
<pre>{{ form | json }}</pre>
</div>
I noticed it with the down arrow key. I tab onto the field and press the down arrow. The first key press updates the model. The second key press updates the form element but not the model. The third key press and every key press after that updates the model as you would expect.
The Fix
Add an extra option with a blank value to the top of the list. By making the value blank, it will not interfere with form validation (marking the field as required, for instance). Also, AngularJS does allow you to include one static option when you bind to an array. From the AngularJS docs:
Optionally, a single hard-coded <option> element, with the value set
to an empty string, can be nested into the <select> element. This
element will then represent the null or "not selected" option.
UPDATE: Browser Diff
I've noticed that Chrome will update the display of the model with each keypress of the down arrow (except the second keypress when the static default option is not present, obviously). Chrome was the browser I used when writing the fiddle. Firefox, on the other hand, does not update the display of the model until i tab or click out of the field. Internet Explorer 11 updates the model "on the fly" similar to Chrome, but I wasn't able to reproduce this "2nd keypress issue" on IE 11. I don't have any other browsers to test on.