Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<option>s appear not to be selectable at creation when disabled #2803

Closed
StoneCypher opened this issue Jan 4, 2015 · 8 comments
Closed

<option>s appear not to be selectable at creation when disabled #2803

StoneCypher opened this issue Jan 4, 2015 · 8 comments

Comments

@StoneCypher
Copy link

The react implementation of <select> does not appear to allow an <option disabled> to be selected. This is correct behavior in the user timeline, but not at initial creation.

HTML allows for a <select> to offer a selected <option disabled> at creation time by wording its disallow to only update a select to a disabled option, and disallows the form to post if a disabled option is still selected. Whereas not explicitly allowing the pre-loaded <select> to select an <option disable>, all major browsers permit this.

HTML does not allow a <select> to not have a selected option at any time. As such, it is idiomatic to have a disabled empty option (or one with placeholder text such as "pick a color") be the selected element at load time.

I believe that this example code should load to the first <option>, but instead it loads to the second. If you remove disabled from the unshifted element, then (and only then) is it selected at load time.

/** @jsx React.DOM */

var TestCase = React.createClass({

    render: function() {

        var options = [1,2,3,4,5,6,7,8,9,"Eisenhower"].map(function(X) {
            return <option>{X.toString()}</option>;
        });

        options.unshift( <option value disabled selected> -- Select Eisenhower -- </option> );

        return <select>{options}</select>;

    }

});

Please advise.

@waldreiter
Copy link
Contributor

I fixed your code a bit. Should work okay now.

var TestCase = React.createClass({
    render: function() {
        var options = [1,2,3,4,5,6,7,8,9,"Eisenhower"].map(function(X) {
            return <option key={X}>{X.toString()}</option>;
        });

        options.unshift(
            <option key='default' disabled={true}>
                -- Select Eisenhower --
            </option>
        );

        return <select defaultValue='-- Select Eisenhower --'>{options}</select>;
    }
});

@StoneCypher
Copy link
Author

That isn't actually the same thing. For example, it is entirely legal, and occasionally useful, to have two different <option>s with the same descriptive text. Should the placeholder match one, then the placeholder is no longer selectable.

@StoneCypher
Copy link
Author

That is to say, in order to have a control without subtle failure cases which do not exist in HTML, the selection actually needs to occur on the <option> rather than on the <select>.

@waldreiter
Copy link
Contributor

If you have <option>s with the same descriptive text, then you can give each option a value attribute. This can then be used to set the defaultValue. Like this:

var HalloSelect = React.createClass({
  render: function() {
    return (
      <select defaultValue='hallo2'>
        <option value='hallo1'>Hallo</option>
        <option value='hallo2'>Hallo</option>
      </select>
    );
  }
});

@StoneCypher
Copy link
Author

Oh. 😄

That does indeed solve my problem. Thank you, @cody . 👍

I still feel like this should be possible, and that it's not documented may confuse others, but this is no longer a necessity as far as I understand it.

However, this is still a behavioral contrast to HTML, which seems mildly undesirable.

@nhunzaker
Copy link
Contributor

nhunzaker commented Jul 11, 2017

Wrote up a test case based upon the discussion here:

https://jsfiddle.net/84v837e9/140/

I've also migrated this into a DOM test fixture so that we can make sure the behavior is correct:

#10142

I believe everything is working as intended on 15.6.x. It actually looks like this might be a problem on the current local build of React, but I'm working on that separately.

When a select option has no value attribute, it uses the text content as the value. I can see a few use cases (though please help me to identify more if I've missed any):

A select with a disabled option:

<select defaultValue="">
  <option disabled>Please select an item</option>
  <option>0</option>
  <option>1</option>
  <option>2</option>
</select>

The default select option rendered here will be "0". The first option is disabled, so it is not selected.

This is because the value of the disabled option is not an empty string, it is "Please select an item". Because there is no value attribute, it uses the string children of the option element.

A select with a selected disabled option that has a value:

<select defaultValue="">
  <option value="" disabled>Please select an item</option>
  <option>0</option>
  <option>1</option>
  <option>2</option>
</select>

Here, the selected option will be "Please select an item" because the select's value and the options value are the same. "Please select an item" is not selectable:

selectable


Default options, like "Please select" need to have a value equal to the valid empty state for the select. That way, React can associate the value attribute of the select and option tag to know what should be selected.

I'm going to leave this open for now. Looks like working through this issue might have uncovered a bug in the master build of React.

@gaearon
Copy link
Collaborator

gaearon commented Oct 2, 2017

If it’s still a problem in React 16 please file a new issue.

@StoneCypher
Copy link
Author

Re-filed as #11099 and #11100

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants