Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Boolean attributes #2158

Open
trusktr opened this issue May 12, 2024 · 1 comment
Open

Boolean attributes #2158

trusktr opened this issue May 12, 2024 · 1 comment

Comments

@trusktr
Copy link
Contributor

trusktr commented May 12, 2024

Continued from

Describe the bug

If I write

return <custom-element foo={someBoolean}></custom-element>

there is no guarantee that the custom element will have a JS property that is designed to handle the boolean value or to reflect it back to an attribute. We need explicit control.

Your Example Website or App

n/a

Steps to Reproduce the Bug or Issue

  1. try using various custom elements and realize you can't explicitly control boolean attributes

Expected behavior

As a user we expect to have more control over boolean attributes vs boolean JS properties.

Screenshots or Videos

No response

Platform

  • OS: any
  • Browser: any
  • Version: 1.8.17

Additional context

No amount of automatic rules or heuristics can solve this. We need bool:foo= to make it explicitly pickable by the user.

For example,

  • one custom element might be able to handle a .foo = bool JS property and reflect it to an attribute, another one might not (it might only detect the presence of an attribute in its CSS style), and another might accept the JS property but not reflect.
  • a user of any of the elements in the previous point might want to set the JS property, or they might need to explicitly set the HTML attribute for the element's features to work if the element has no JS property, or they might need to use the HTML attribute even if the custom element supports a JS property because the user may want to use that in their own CSS selector, etc.

There's absolutely no way we can determine a rule for this that works for everyone.

The only thing we can do is provide bool:foo= to give users the choice that they need.

Lit's html template tag supports the following:

  • foo= - always sets an attribute (the element may independently map this to a JS property)
  • .foo= - always sets a JS property (the element may independently reflect this back to an attribute)
  • ?foo - always adds the attribute if the value is truthy, always removes the attribute if the value is falsy (the element may independently map this to a JS property)

The Lit templating is fully decoupled from the concept of how any element underneath handles attributes and properties, it is 100% up to the user to decide if they set attribute strings, JS properties, or add/remove boolean attributes. This makes Lit's templating 100% compatible with 100% of all possible built-in and custom elements that could ever exist.

Solid's JSX and html template does the following:

  • foo= - automatic heuristic: set the string attribute on built-in elements by default (with special cases), or set the JS property on custom elements
  • prop:foo= - always set the JS property
  • attr:foo= - always set the attribute

But Solid has no bool:foo=, which is the missing piece. We 100% need this piece if we want to be fully compatible with custom elements (we will never know the set of all boolean attributes that arbitrary custom elements can define, and not all custom elements will automatically map boolean JS properties to boolean attributes).

In comparison, React's new custom elements support,

is not as good as Lit's or Solid's above because it is automatic with no manual control (cc @josepharhar, @sebmarkbage, @gaearon, @rickhanlonii), although this is a much better state than before that at least allows custom elements to have a path such that their implementation fully works in React when CE authors follow certain rules (always handle JS properties, and liberally reflect primitive values back to attributes). But not all CE authors are going to follow these rules; some of them may not even know or care about React.

To get this support or lack of support recognized across frameworks, we need to update custom-elements-everywhere so we can test this in all frameworks:

@josepharhar
Copy link

If the custom element is upgraded and has a setter for the property, then when react renders it should assign the boolean you're providing in the JSX into the custom element's property instead of attribute.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants