Skip to content

Boolean attribute doesn't behave as might by expected for web component #162

Open
@jrencz

Description

@jrencz

Hi!

I noticed that the chosen behaviour for boolean transform is

const string: Transform<boolean> = {
stringify: (value) => (value ? "true" : "false"),
parse: (value) => /^[ty1-9]/i.test(value),
}

which is:

it's true if value of attribute starts with t, y or a non-0 number.

and it's tested:

true-prop="true"
false-prop="false"

On the other hand HTML boolean (https://developer.mozilla.org/en-US/docs/Glossary/Boolean/HTML) attribute is considered true just because it's present:

If an HTML tag contains a boolean attribute - no matter the value of that attribute - the attribute is set to true on that element. If an HTML tag does not contain the attribute, the attribute is set to false.

That leads to interesting behaviour - if attribute is present, but not assigned a value (i.e. it's HTML Boolean), it's cast to false (not just undefined but actually the polar opposite)

I detected it wile using with Lit booleans (https://lit.dev/docs/templates/expressions/#boolean-attribute-expressions) - Lit implements HTML boolean.


I think it can be resolved in a backwards compatible way.

I see that transforms are given the attribute name as 2nd argument

So parse could be made into

  parse: (value, attribute) => 
    // Check if it's HTML boolean
    value === undefined
    || value === ''
    || value === attribute
    /// Check if it's boolean by value
    || /^[ty1-9]/i.test(value), 

I don't have an idea for stringify, though. It would have to be a choice of the author (i.e. differently named transform) I guess

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