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

syntax for choosing setting a property vs attribute on elements #4416

Open
trusktr opened this issue Jun 20, 2024 · 11 comments · May be fixed by #4419
Open

syntax for choosing setting a property vs attribute on elements #4416

trusktr opened this issue Jun 20, 2024 · 11 comments · May be fixed by #4419

Comments

@trusktr
Copy link

trusktr commented Jun 20, 2024

Describe the feature you'd love to see

It is not possible to guess 100% of the time whether an element user needs to set a property, or an attribute.

Does this set an attribute, or a property?

return <some-element foo={[1, 2, 3]} />

Answer: it depends, sometimes Preact sets the .foo property, sometimes Preact sets the foo attribute. The user has no control over this.

The implementation of an element can vary (and may be out of the Preact user's control):

  • some elements handle properties only
  • some elements handle attributes only
  • some elements handle both
  • even if an element handles one or the other, or both
    • a user might want to set the attribute
    • or the property
    • or both
  • user might want to add or remove an attribute based on a boolean (regardless if they also want to set the corresponding JS property or not)

Design choices out of the control of Preact:

  • some element authors rely on attributes for styling :host with attribute selector
  • some element users may want to set an attribute for styling from the outside regardless if the element accepts a JS property (they could set the JS prop, and the element would work, but their CSS would not be able to select the element)
  • etc

It is not possible for Preact to always guess correctly which of the above cases the user will want, and the Preact user needs control.

Additional context (optional)

Users need a way to express whether they want to set an attribute, or a property, or both. We also need to be able to add/remove attributes based on booleans.

Lit, Solid.js, and others have (sometimes only partial) solutions to this. For more details on the solutions other frameworks have, see this new test proposal for custom-elements-everywhere:

Possible solution idea

Solid.js has JSX syntax such as attr:foo=... and prop:foo=... for setting an attribute vs a property, but no boolean support. Pota, a library that is built on Solid.js, has its own JSX and html syntax that adds bool:foo=... support. Etc.

Preact could choose to adopt a similar approach, which is valid JSX syntax.

An alternative html template string tag for Preact could also provide Lit-like syntax (.foo=..., foo=..., and ?foo=...).

@rschristian
Copy link
Member

rschristian commented Jun 20, 2024

Answer: it depends, sometimes Preact sets the .foo property, sometimes Preact sets the foo attribute. The user has no control over this.

While I don't disagree with the premise/request, and have written up minor forks/patches that add this, there are quite defined rules. It's not random or a guess: if the provided label has a DOM property, and isn't from a small list of excluded labels, it gets set as a property, else, attr.

Preact (and other UI libs) aren't "guessing" at what others expect; they work with the DOM as they see fit. It's up to the individual devs to reconcile the expectations of different pieces of software. More control here would absolutely help devs reconcile those expectations, but I just want to make it clear that it isn't really a project goal to "guess correctly" as you put it.

@trusktr
Copy link
Author

trusktr commented Jun 20, 2024

It's not random or a guess: if the provided label has a DOM property, and isn't from a small list of excluded labels, it gets set as a property, else, attr.

Perhaps "heuristic" or "rules" are better terms. To re-express with those words, no heuristic or rule can satisfy all scenarios because all scenarios can only be users picking which to use.

@trusktr trusktr changed the title we need syntax for choosing setting a property vs attribute on elements syntax for choosing setting a property vs attribute on elements Jun 20, 2024
@rschristian
Copy link
Member

Not quite what I meant, no. We largely set what we set, we're not looking to satisfy any scenarios beyond "works with DOM APIs correctly". Anything beyond that is a non-goal of the project really, something for users to address. It's not a concern of the project if it doesn't enable a CSS selector, for example.

Not having great tools for users to address these issues is, however, a valid issue for the project, if that makes sense.

Minor (perhaps frivolous) semantics, I know, but I want to clarify project goals.

@trusktr
Copy link
Author

trusktr commented Jun 21, 2024

I'm not sure what's the debate. In my mind it's a valid request (and likely project goal) to be able to control DOM elements with a DOM framework like Preact (wanting to set an attribute to use for CSS selecting is but one of many reasons), but of course that's up to each framework.

I changed the issue template to feature request (accidentally chose bug first).

@rejhgadellaa
Copy link

I recently ran into the popover property not accepting boolean values, but the attribute can be a boolean (it will then default to auto). So this:

<menu popover />

Will actually try to set Element.popover = true (which is an error)

You have to write:

<menu popover="auto" />

Not a big problem, but annoying 😅

@rschristian
Copy link
Member

rschristian commented Jun 21, 2024

@rejhgadellaa have you checked the latest version? I believe that was a bug that was corrected.

Edit: Never mind, hasn't been released yet. Fixed in #4393 though

@rejhgadellaa
Copy link

@rschristian oh sweet, I actually thought this was "working as intended", and maybe even more of an issue of the spec where the property and attribute don't accept the same argument types. Thanks!

@hesxenon
Copy link
Contributor

why not check the static observedAttributes? If my custom element is interested in e.g. disabled I must add "disabled" to the observedAttributes property anyway - which should sufficiently state that I am indeed interested in the content attribute and preact should not just drop that

@rschristian rschristian linked a pull request Aug 20, 2024 that will close this issue
@OEvgeny
Copy link

OEvgeny commented Jan 31, 2025

why not check the static observedAttributes? If my custom element is interested in e.g. disabled I must add "disabled" to the observedAttributes property anyway - which should sufficiently state that I am indeed interested in the content attribute and preact should not just drop that

There may be attributes one does not want to observe. Better to have a way from Preact/JSX to denote either the attribute or property needs to be set as this sometimes can influence the behavior of particular custom element.

In addition developer using Preact may not have control over the Custom Element code, so they won't be able to adjust. Even extending a custom element class may not be an option in certain cases.

@hesxenon
Copy link
Contributor

Okay, so basically I already worked around my issue by reflecting the IDL attributes to the content attribute, as hinted towards in the MDN docs (.value seems to be the exception, not the norm) and I don't have anything against the sigils approach, but your answer is a bit paradoxical...

why not check the static observedAttributes?

There may be attributes one does not want to observe

If a CE Author does not want to observe a content attribute they should not put it in something that's literally called observedAttributes.

If a CE defines that it is interested in changes to the content attributes by listing it there it stands to reason that it will also react in some way to changes in those attributes (presumably by updating the IDL attribute, as hinted to in the MDN docs).

A developer that does not have control over the CEs code has nothing to do with it, no preact dev has control over the native elements code either yet we can easily use them in plain HTML (content) and preact (IDL).

Again, if preact/react would rather go the sigils route that's fine by me but saying that the semantics of observedAttributes change just because preact/react is being used seems... wrong.

@OEvgeny
Copy link

OEvgeny commented Jan 31, 2025

I mean Preact shouldn't rely solely on the particular CE observedAttributes static field to determine how to set a given property/attribute correctly. There always should be a way to adjust the behavior from JSX.

If a CE Author does not want to observe a content attribute they should not put it in something that's literally called observedAttributes.

That's what I'm talking about. If the attribute isn't present in the array, this doesn't mean it should be treated as a property.

Moreover unobserved attributes can and may change in particular cases and there might be reasons for CE developer to refrain from the API usage.

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

Successfully merging a pull request may close this issue.

5 participants