React: Boolean element attributes (disabled, checked, etc.) in JSX

Created on 24 Jan 2014  路  20Comments  路  Source: facebook/react

This is how I've been conditionally putting the disabled attribute on elements, with a boolean variable:

<input disabled={isDisabled} type=... />

When isDisabled is falsey, the attribute won't be output. When true, it will output the following, which works in browsers but is against the HTML5 spec:

<input disabled="true" type=... />

I could get in line with the spec by setting disabled="disabled" on the element, but that requires a ternary operation instead of a simple boolean:

<input disabled={isDisabled ? "disabled" : false} ... />

Ideally, my current bit of JSX (at the top of this issue) would output this HTML, assuming disabled is set to true:

<input disabled type=... />

More generally, if a known boolean attribute gets assigned a variable set to true as in my example, JSX should output just the attribute as per the HTML5 spec.

Most helpful comment

For those who are looking for work-arounds, for the time being, I found this on StackOverflow.

All 20 comments

Agree that we should go with disabled="disabled" or just disabled. The former is XHTML-compatible, which may be desirable. Want to take a crack at a PR for this? :)

Sure, I'll take a look at it in the next few days.

Personally I'd rather emit HTML5-style bare attributes, but XHTML compatibility could be good as you say. Some sort of configuration or option to control that?

I'm for the bare attributes! Although I don't think we should have configurations over this... it's a bit too granular imo.

I don't see why it should be configurable, if it can emit bare attributes, it should use disabled="disabled" as a fallback for when the browser isn't up to spec. EDIT: Hmm, IE8 actually supports bare attributes as well, are we actually supporting any browsers that don't? If so we should just go ahead and make it the only behavior.

I think it's worth considering adding bare attributes to JSX as well. EDIT: Oh wow, it already does, I had no idea.

@syranide Bare attributes were the standard way to do things before XHTML came along and told everyone to do disabled="disabled", so it should be supported everywhere (except in XHTML documents, of course).

@spicyj Cool, then it should be an easy and safe change right?

I think so.

cc @yungsters - I vaguely remember doing this for a reason. But if bare attributes work, then cool.

I think this is a good idea, and the only reason it hasn't already been done is probably due to oversight.

You'll have to update DOMPropertyOperations.createMarkupForProperty and DOMPropertyOperations.setValueForProperty. Also, does this make sense for all attributes in DefaultDOMPropertyConfig that are configured with HAS_BOOLEAN_VALUE?

@yungsters Probably need to validate that all properties with HAS_BOOLEAN_VALUE really are meant to be bare.

Yeah. If you find that there are some that should not be "valueless", may we need a HAS_NO_VALUE configuration.

Closed with #1005

For those who are looking for work-arounds, for the time being, I found this on StackOverflow.

In react, it appears the 'checked' attribute on checkbox input fields do not set the actual html checked attribute, just the javascript checked property on the element. This causes issues with css selectors depending on the checked selector.

Take this example. The css selector does not see the first element as checked.

When I create a checkbox in react the checked="checked" attribute is missing even though in the jsx i have set checked={true}
screenshot 2016-11-02 14 00 16

@ jamescharlesworth I too have this problem. Did you find any solution to this?

@wnr dont know if this has been fixed by the React team yet, but the quick and dirty solution was to manually set the attribute value on change

@wnr
I followed this way.

let disabled = isReadonly ? {'disabled' : 'disabled'} : {};

This causes issues with css selectors depending on the checked selector.

You should not write CSS selectors like [checked]. This is just a wrong way to approach the problem. Browser doesn't guarantee that attributes stay synced with properties.

In your example, instead of

input:not([checked]):disabled + label::after {

you should use :checked pseudoclass:

input:not(:checked):disabled + label::after {

Then it works with expected when toggled through JS (including React).

@kkdatkiran - It worked, thanks

xvcvb

Was this page helpful?
0 / 5 - 0 ratings