As far as i can see we can't use self closing tags (
Custom Elements can not be self-closing per spec. See w3c/webcomponents#624
Self-closing tags are not allowed for Custom Elements, because they are not allowed in HTML5 in general, outside foreign elements. Regular HTML elements allow the self-closing solidus _only_ on void elements, on which they are optional and have no effect.
Lit-html uses the native template parser in browsers, so it will allow whatever syntax is allowed by the HTML5 specification (assuming the browsers implement correctly). The main advantage of this strategy is that we do not have to implement a parser, because we use the available builtin parsers. It is unlikely that we will want to deviate from this strategy to add support for features like self-closing tags that are not part of the HTML5 spec.
There are ways to do regex replacements on the template strings to support self-closing tags, but I don't think it's really worth the code or extra scans.
I'll leave this issue open to see if there's a lot of demand though.
Maybe we can create a config system for this kinda features ? I don't like bloated libraries too. But I think lit-html should be a solution for runtime problems. At future maybe there can be a typescript plugin(transformer) does this kinda compile time problems too which honestly i would prefer that and working about it. But since that time we need at least a temporary solution for this kinda problems i think. I'm developing a custom element library just like lit-element so i created symlink from lit-html's src folder to my lib folder now tsc compiles lit-html inside my project and i can implement some changes that i need so this is not really a problem for me currently. I think more people should prefer lit instead of solutions like react or vue but people who are used to jsx nags about this kinda small syntax problems constantly whenever i show to them. I tried not using a full regex search and some small string processing but im pretty sure somebody can write a better implementation that is good enough people would prefer losing that speed for this feature.
IMO I don't like the idea of supporting self-closing tags because that's not really a thing in HTML5, mostly it's just either void elements or normal elements. Adding more processing just to solve something that isn't standard and that any decent IDE/Text Editor will autocomplete anyways seems like a waste to me.
Same, and I stand by my point in: https://github.com/Polymer/lit-html/pull/631. We shouldn't circumvent the spec for the argument of "React/JSX popularized self-closing tags, and those users are familiar with it".
Having worked with Polymer since v1 and with React, I can say personally that the main thing that I found as a nice to have from the React/JSX self closing tag is the neatness of the code. I often found the autocomplete of an editor more than enough to handle the "burden" of a closing tag.
With that said, I don't see why someone couldn't write a basic compile plug-in to handle a self closing tag to what the DOM would expect. This would allow a user to opt-in knowing the pros and cons of it without affecting the runtime.
@stramel The downside to that approach is that either the element creator has to precompile their element before publishing, or expect the end user of the elements to add the plugin even if they don't want to use self closing tags themselves.
When needing to make a choice, we're going to optimize for familiarity to HTML over JSX. HTML doesn't support self-closing tags, so the impetus here is much less.
I'll point out that this can be pretty easily done with a custom TemplateResult class - so one should be able make their own fairly trivial subclass of TemplateResult that overrides getHTML() and runs the regex/replace that expands self-closing tags.
Good discussion. The key here, to me, is does a change comply with or run
counter to, in this case, the HTML5 specification? I understand a lot of
developers are used to and like self-closing tags, it seems like a change
that is either unnecessary or adds complexity beyond the scope of the
intended library. Maybe this would be a good tooling project, but I'm
hesitant to advocate for this type of change in lit-html itself.
Just saw this, htm by @developit https://github.com/developit/htm
Interesting that he is supporting self-closing tags in his library.
EmpatiElement/Template:EmpatiTemplate.getHTML() if anybody needs that's how im using it.
Ive just got bitten by this.
While converting a project from JSX to lit-html / lit-element i kept the self closing tag as in JSX:
const obj = {value: "great"}
return html`<my-element .mood=${obj}/>`;
At first look worked. The element is instantiated and upgraded but the object property being passed to it was converted to '[object Object]'
Debugging i found that the part was converting the value to string because part.single was false
Finally the culprit was that i was not using quotes around the property value as suggested here
Those variations worked:
return html`<my-element .mood="${obj}"/>`;
return html`<my-element .mood=${obj}></my-element>`;
Here's the complete example
https://codepen.io/blikblum/pen/dwjvyX?editors=1000
I think the not support for self closing tag for web components should be well documented, since IMO will be a common situation
It is well documented in the HTML spec :)
Average programmers do not read specs, many are not even aware of its existence, so documenting somewhere will save a bunch of issues when/if lit-html becomes popular among them. And don't expect detailed issue with sample code, already debugged like i did. Is just: "does not work"
Anyway, this issue is particularly catchy because, apparently, works with quotes or using string properties. Than add an object property and suddenly does not work
There could be a place in the docs for this under Template Structure: https://lit-html.polymer-project.org/guide/template-reference#template-structure
cc @arthurevans
Hi, I understand and support the logic behind not supporting self-closing tags, but it is confusing coming from JSX. A heads-up in the documentation would be good enough.
This is not planned.
Here a way to implement this on top of lit-html, if anybody is looking for:
function htmlWithSelfClosingTags(strings, ...values) {
let tagName
strings = strings.map(part => {
const hasEnd = part.indexOf('/>') >= 0
if (tagName && hasEnd)
part = part.replace(/^([^<]*?)\/>/, '$1></' + tagName + '>')
if (!tagName || hasEnd)
tagName = part.match(/<([^ >]+)[^>]*?$/)?.[1]
return part
})
return html(strings, ...values)
}
I just export this as html and use it instead of lit-html's function.