Skip to content

Can't declare Boolean attributes with default of true? #1812

Description

@JanMiksovsky

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.

Activity

  1. punzki commented on Jun 9, 2015

    @punzki

    +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-repeat to 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-attr to 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 property foo in Objects in arr, and passes them on correctly to x-test's bool-attr property.

  2. arthurevans commented on Jun 10, 2015

    @arthurevans

    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.foo isn't being deserialized here. You're assigning x-test.boolAttr the value of item.foo.

  3. punzki commented on Jun 10, 2015

    @punzki

    @arthurevans - That's precisely my point, that it is confusing, and inconsistent. When you put x-test in regular HTML markup, you set x-test.boolAttr by the presence/absence of the bool-attr HTML boolean attribute. But when it's used inside a dom-repeat, you're supposed to assign it by using a non-boolean HTML attribute.

  4. adalinesimonian commented on Jun 15, 2015

    @adalinesimonian

    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 evilLairRequired with a default of true, there would be a property evilLairOptional with a default of false.

    Basically, what I'm getting at is: what's an expectable use-case where this is not possible?

  5. JanMiksovsky commented on Jun 15, 2015

    @JanMiksovsky
    Author

    @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-size attribute 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 than minimize="false". Something like not-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.
  6. jlg7 commented on Jun 15, 2015

    @jlg7

    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 favorite where 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.

  7. kevinpschaaf commented on Jun 15, 2015

    @kevinpschaaf
    Member

    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 how type: Boolean values are deserialized by default.

    That said, there are some options if you choose to go forward implementing this type of API for your elements.

    1. Use type: Object - this actually hints Polymer to use JSON.parse which result in the desired behavior ("true" and "false" parse desired):
      http://jsbin.com/zawale/edit?html,output
    2. Implement a custom serialize/deserialize function 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
  8. JanMiksovsky commented on Jun 16, 2015

    @JanMiksovsky
    Author

    @kevinpschaaf I think Polymer's position is reasonable. Thanks for letting us know about those options!

  9. jptrainor commented on Sep 29, 2015

    @jptrainor

    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.

  10. arthurevans commented on Sep 29, 2015

    @arthurevans

    This 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:

    http://jsbin.com/gosaza/edit?html,output

  11. jptrainor commented on Sep 30, 2015

    @jptrainor

    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.

  12. arthurevans commented on Sep 30, 2015

    @arthurevans

    Glad to hear it 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions