Home > OS >  Vuejs Boolean Attributes (Truthy and Falsy values)
Vuejs Boolean Attributes (Truthy and Falsy values)

Time:10-07

I'm reading the Vuejs docs and get confused at some point when I was at the part of Attribute Bindings (link to the specific part : https://vuejs.org/guide/essentials/template-syntax.html#boolean-attributes).

As far as I'm aware, in JavaScript, empty strings ("") are considered as falsy.

But, in Vuejs Docs:

<button :disabled="isButtonDisabled">Button</button>

The disabled attribute will be included if isButtonDisabled has a truthy value. It will also be included if the value is an empty string, maintaining consistency with <button disabled="">. For other falsy values the attribute will be omitted.

Here, they evaluate the empty string as a truthy value !

If someone has an explanation ? it's something that we should be aware of, or it's just a choice of Evan You (creator of Vuejs), but based on what ?

Thanks.

CodePudding user response:

I understand there is already bias against this topic, but I'd ask for a chance to revisit it in more detail.

After the necessary removal of proprietary enumerated attributes behavior, the boolean attributes behavior has been made less intuitive, more difficult, and error-prone.

Less intuitive because HTML attributes take string values, so it was widely understood a boolean value of false would result in no attribute at all, e.g. would result in . This was ideal because the code for controlling these attributes naturally produced boolean values, i.e. it Just Worked. Attributes that need strings "true" and "false" were easily provided with bool.toString(), which made sense because HTML attributes only take strings. More on these attributes below.

Also, Vue now matches native setAttribute('attr', false) which results in attr="false", so you might expect Vue to give null equal treatment, e.g. setAttribute('attr', null) results in attr="null", but it doesn't.

More difficult because developers now have to work against JavaScript to ensure their data, template expressions, methods, and/or computed properties result in an unnatural null value. It may seem as simple as :attr="bool || null" but any computed or method with logic branches the dev now has to go the extra mile to ensure null and not false is going to be the final output of the branching. Also, this logic :attr="bool || null" just makes my brain go Huh? If false give me a null? Never written an expression like that before, would hate to have to scatter that all over my templates.

More error-prone because the odds of a value being a boolean are very high and the ubiquitous boolean is now a liability in templates. One way to mitigate this new risk is to make all things that could be false be null instead. This avoids the possibility of another dev using something that isn't boolean attribute safe. A terrible pattern, but if it means reducing risk devs may go that route. Gross.

Okay, on to attributes that take "true" and "false" strings... Sure, attributes like aria-required need a string value of "true" or "false", however... Attributes like contenteditable are likely given string values by the developer because "true" and "false" are just two of several possible strings the developer can set on that attribute. Devs can write code like :contenteditable="plainText ? 'plaintext-only' : 'false'", so it's strange for Vue to go out of its way to cast booleans to strings for the developer to support this case. Same story with aria-invalid. It supports the strings "grammar", "spelling", "true", or "false". The developer will supply one of the four strings, not one of two strings or a boolean. Yes, someone could write the latter, but you see where I'm going. Same again for aria-haspopup, which supports 7 different string values, including "true" and "false". And then there's aria-expanded and aria-pressed, which support "true", "false", and "undefined" (pressed also supports a fourth string "mixed"). But if I give Vue undefined it doesn't cast it to a string like it does for false it removes that attribute, which made sense in Vue 2 but not now. Vue requires the developer to supply the string "undefined", but casts false for them. Vue does this because it mistakenly believes there's something special about attributes that take "true" or "false" strings. This is not great and it's made even more weird because setAttribute('attr', undefined) normally results in attr="undefined".

CodePudding user response:

An empty string as value for the disabled HTML attribute, on elements which support it, is interpreted as a truthy value. This is the HTML standard.

<input disabled />
<!-- exact equivalent of... -->
<input disabled="" />
<!-- exact equivalent of (in Vue template) -->
<input :disabled='""' />
<!-- exact equivalent of (in JSX) -->
<input disabled={""} />

When provided as a binding JavaScript expression, Vue will not include the attribute when the expression is falsy, except when it evaluates to empty string. In that case, Vue will include the attribute, without changing its value.

Why is the warning there?
Because empty string is typically interpreted as falsy value in JavaScript and they identified this as a potential source of subtle bugs.

The attribute's behavior is not Vue team's decision. It's W3C's decision.

  • Related