This issue improves parsing of custom elements and makes it possible to distinguish between properties and attributes. Here are my considerations/thoughts.
TLDR: goto conclusion for a conclusion :-)
lit-html
allows setting both attributes (myattr="value
) and setting properties on the element (.myprop="value"
).
In reality any property (and any attribute) can be set on any element so I'm considering allowing doing this through a configuration. I'm a bit in doubt of allowing this by default because I fear it would introduce a risk that spelling mistakes wouldn't be cached by the plugin.
Built in HTML tags
All in all for built in HTML tags I use the list of attributes from (vscode-language-service)[https://github.com/Microsoft/vscode-html-languageservice) and plan on using the typescript lib.dom.d.ts
for finding properties on individual elements. I haven't decided what to do on the "null vs undefined" challenge described below.
Null vs undefined
Also properties have different behaviours when it comes to null
and undefined
. For example when setting HTMLTextAreaElement.value
it clears the text on the value null
and sets the text "undefined" on the value undefined
. (See this codepen https://codepen.io/runem/pen/vbqvqq) However when setting min
on an of type "range" the attribute value is set to min="null"
. I'm not sure of where to find more information on these behaviour (other than reading the individual specifications) so if anyone knows, please give me a tip.
Custom elements
When parsing custom elements (non LitElements) we only have to look at static get observedAttributes() { return ['c', 'l']; }
and public class fields. In addition we should also look at public properties defined on HTMLElement.
Attribute only
It's possible to have observed attributes only (without a property behind):
class MyElement extends LitElement {
static get observedAttributes() { return ['c', 'l']; }
}
Property only
And it's possible to have properties on the element without an attribute behind. This plugin would look at public class fields to find these (This can be done in Typescript and in Chrome 72)
class MyElement {
myProperty = "hello";
}
I also plan on looking at assignments in the constructor to find properties on a given class.
LitElement custom elements
Parsing LitElement custom elements is a superset of parsing custom elements.
Default:
When using the lit-element
property decorator (@property() size
) (or static get properties()
) the property name is by default added as an observed attribute lowercased.
By default, LitElement creates a corresponding observed attribute for all declared properties. The name of the observed attribute is the property name, lowercased
Property only:
When using the "{attribute: false}" config the corresponding attribute is not observed.
Backer attribute with another name:
When using the "{attribute: 'other-attr'}" config the corresponding attribute is observed with another name.
Conclusion
To conclude I plan on keep two lists on each html tag: a list of attributes
and a list of properties
.
I will also have to expand the custom element parser to include the points I describe above. This primarily includes better support for attributes/properties defined without the lit-element property-decorator :-)