Repository navigation
Can't declare Boolean attributes with default of true? #1812
Description
Activity
+1 to being able to use
prop="false"and have Polymer deserialize it as a Boolean false. Any other String value can be true. Or maybe also accept"0".One more thing. It also causes more confusion when I use
dom-repeatto create a bunch of custom elements, with Boolean properties. What am I supposed to set for the attribute?<template is="dom-repeat" items="{{arr}}"> <x-test bool-attr="{{item.foo}}"></x-test> </template>
If Polymer were strict about "Boolean properties set based on the existence of the attribute", then there is no way to set
bool-attrto false, since there's no way to conditionally set the presence of an attribute (you can only set an attribute's value). But actually, Polymer is fine with the above syntax... it reads the Boolean value of propertyfooin Objects inarr, and passes them on correctly tox-test'sbool-attrproperty.Note that this isn't really Polymer's definition of a boolean attribute, it's HTML's definition of a boolean attribute:
http://www.w3.org/TR/2008/WD-html5-20080610/semantics.html#boolean
I think there's a tension here between something that's arguably more flexible (foo="false") and something that's arguably more idiomatic with native elements (presence == true). Even the web platform is incoherent here, since ARIA uses string values for "true" and "false".
@punzki you're confusing setting an HTML attribute and data binding to a property. The value of
item.fooisn't being deserialized here. You're assigningx-test.boolAttrthe value ofitem.foo.@arthurevans - That's precisely my point, that it is confusing, and inconsistent. When you put
x-testin regular HTML markup, you setx-test.boolAttrby the presence/absence of thebool-attrHTML boolean attribute. But when it's used inside adom-repeat, you're supposed to assign it by using a non-boolean HTML attribute.I'm curious to better understand the use-case for having a boolean property have a default of true. Would it not be possible to simply reverse the logic behind the property such that the desired functionality would be possible with a default of false?
For example, assuming we're working with an element that validates villains to see whether or not they're fit of being someone's arch-nemesis, instead of using
evilLairRequiredwith a default of true, there would be a propertyevilLairOptionalwith a default of false.Basically, what I'm getting at is: what's an expectable use-case where this is not possible?
@vsimonian There are cases where the most natural and desirable attribute name would be framed in the positive. While attributes are just symbols, and their meaning can be inverted and still make logical sense, an API is tantamount to language, and humans want language to read naturally. In some cases, the positive form of a word may be more concise or common than the negative form. (Some rare words like "inert" have no opposite form.) In other cases, the negative form may be misleading or inaccurate. And it's often desired that an API should mirror the corresponding terms in the user interface.
- A component wants an
auto-sizeattribute that defaults to true. It's hard to come up with a natural-sounding word or phrase that means the opposite of "auto-size". - A window component has a maximize attribute that defaults to true. The meaning of
maximize="true"is different thanminimize="false". Something likenot-maximized="false"may be accurate but quite awkward and hard to parse. - A site has some type of object that can be marked as a "favorite", and for whatever reason, the default is true. Because the UI uses the term "favorite", it's desirable to have the attribute be called
favorite, with a corresponding default value of true.
Reacted by René Paw Christensen and michaelowolf- A component wants an
I encountered this when migrating elements from 0.5 to 1.0. To avoid coming up with corresponding negative forms, I just used an additional word in front of the attribute names to represent an attribute is disabled or its effects have been inhibited or its dimensions have been reduced (something like
disable-).Although more than one word, this seemed to:
- preserve the UI jargon
- aide in keeping the inherent truth and default behavior of the element
- provide type hinting for attributes named similar to
favoritewhere its boolean nature is rather obscure
The prefix
disable-may not be great in all contexts but other familiar words may be juxtaposed to have the similar effects.As Arthur mentioned, Boolean attributes have a specific platform meaning from which we do not want to stray. We also feel that the practice of defaulting booleans to false makes sense in the vast majority of cases, and places where the platform has strayed (e.g.
draggable="true") were poor design decisions that result in confusing and unintuitive API and are warts of the platform that we are stuck with. For these reasons, we have no plan to change howtype: Booleanvalues are deserialized by default.That said, there are some options if you choose to go forward implementing this type of API for your elements.
- Use
type: Object- this actually hints Polymer to useJSON.parsewhich result in the desired behavior ("true"and"false"parse desired):
http://jsbin.com/zawale/edit?html,output - Implement a custom
serialize/deserializefunction for your element. We intentionally made these methods easily overridable for cases when authors need to augment the default approach.
http://jsbin.com/rerevu/edit?html,output
Reacted by Elias Pinheiro- Use
@kevinpschaaf I think Polymer's position is reasonable. Thanks for letting us know about those options!
- added a commit that references this issue
on Sep 12, 2015 This is a shame. It is not intuitive at all. I need to programatically set the value for paper-input-container's noLabelFloat boolean property It's wrapped in a custome element and I need to disable noLableFloat in some cases.. It cannot be done via a binding thanks to this behaviour. I have to resort to dom-if logic, or write code that sets the property value manually. All that could be avoided if I could just bind a value.
Reacted by RC and Trent BrownReacted by HerberthThis isn't related to data binding. This only affects configuring the element from static markup.
You can easily use a data binding to toggle
noLabelFloat:Many thanks. I got it working with the binding. In my state of confusion when I first countered this I issue I messed up my binding declaration and concluded incorrectly that it didn't work.
Glad to hear it 👍
- added a commit that references this issue
on Aug 7, 2016
The way attributes are deserialized seems to preclude the declaration of attributes that default to true.
From the docs: "Boolean properties set based on the existence of the attribute: if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist)."
That works for attributes with a default value of false. If someone wants the default value, they leave the attribute off. If they want the non-default value of true, they can explicitly say attr="true" (or any string).
But I don't see how to declare support for a Boolean attribute that defaults to true. See http://jsbin.com/neyaxu/1/edit?html,output. Here, I want to be able to override the default behavior by saying red="false". Since Polymer interprets any string value of true, however, it doesn't appear to be possible to declaratively set the attribute to false. That can be done imperatively, but it should also be possible imperatively.
While an attribute's logic can always be flipped such that its default value is false, there are cases where an attribute's obviously API name naturally suggests a default value of true.