preactjs / preact-custom-element

Wrap your component up as a custom element
MIT License
360 stars 52 forks source link

Hyphenated attributes and camelCased properties #53

Open raihle opened 4 years ago

raihle commented 4 years ago

When a component is connected, preact-custom-element will loop through all attributes and set them as props on the component - both with the original casing and with a camelCased name. Automatic camelCasing is also done for observed attributes.

On the other hand, when determining which attributes to observe, the wrapper does not perform any corresponding transformation - it simply uses the given propNames directly (passed in explicitly, or extracted from the component definition). This is a problem because component props are usually in camelCase, while HTML attributes must be in lowercase (usually hyphenated).

If propNames are extracted from the component's propTypes, there is virtually no chance that they will be hyphenated, and the wrapper will only listen for (and try to reflect) changes to a camelCased attribute, not a hyphenated one. However, the spec requires attributes to be in lowercase, and attempting to set a camelCase attribute in a framework like Vue, manually through browser dev tools, or in the HTML source, will lead to a lowercase attribute being set instead. This effectively means that any prop name with a capital letter cannot be observed (as an attribute) by preact-custom-element. Initial values will still be set, since preact-custom-element loops through all attributes and converts them to camelCase props, but that only happens once. The DOM property will also work, but supporting the attribute - for simple data - would be nice.

propNames could be hyphenated if they are explicitly passed, or defined as observedAttributes on the component. But in this case the wrapper will set up a hyphenated DOM property instead of a camelCased one.


Should preact-custom-element camelCase all propNames before defining properties, and hyphenate them before setting observedAttributes?

Should consumers pass in camelCased names for complex types (which will use properties) and hyphenated names for simple types (which will use attributes)? Maybe both forms for simple types?

Should properties and attributes be separated in the preact-custom-element API?