Can anyone tell me why I cannot use variables within lit-html's html
method?
const h1 = 'h1';
return html`
<${h1} class="a-heading ${classes}">
<slot></slot>
</${h1}>
`;
If I replace ${h1}
with h1
that works without problems.
Can anyone tell me why I cannot use variables within lit-html's html
method?
const h1 = 'h1';
return html`
<${h1} class="a-heading ${classes}">
<slot></slot>
</${h1}>
`;
If I replace ${h1}
with h1
that works without problems.
For everyone interested in my solution: Use unsafeHTML
if you can (you should not do that if you wrap any input fields within).
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
// ...
const template = `
<h${this.rank} class="a-heading">
<slot></slot>
</h${this.rank}>
`;
return html`
${unsafeHTML(template)}
`;
literal
or unsafeStatic
as shown in the other answer. –
Altamirano It's 2022 and the solution exists (from the end of 2020 - Issue).
Now you can use something from https://lit.dev/docs/templates/expressions/#static-expressions
For string literals, that you have control of, use literal
template.
You must import special version of html
and use the literal
template.
import {html, literal} from 'lit/static-html.js';
@customElement('my-button')
class MyButton extends LitElement {
tag = literal`button`;
activeAttribute = literal`active`;
@property() caption = 'Hello static';
@property({type: Boolean}) active = false;
render() {
return html`
<${this.tag} ${this.activeAttribute}?=${this.active}>
<p>${this.caption}</p>
</${this.tag}>`;
}
}
and then
@customElement('my-anchor')
class MyAnchor extends MyButton {
tag = literal`a`;
}
For something, that you cannot decorate using the literal
, you can use unsafeStatic
.
Again, you must import special version of html
and then use unsafeStatic
function.
import {html, unsafeStatic} from 'lit/static-html.js';
@customElement('my-button')
class MyButton extends LitElement {
@property() caption = 'Hello static';
@property({type: Boolean}) active = false;
render() {
// These strings MUST be trusted, otherwise this is an XSS vulnerability
const tag = getTagName();
const activeAttribute = getActiveAttribute();
return html`
<${unsafeStatic(tag)} ${unsafeStatic(activeAttribute)}?=${this.active}>
<p>${this.caption}</p>
</${unsafeStatic(tag)}>`;
}
}
html
, is there a workaround? –
Gave Update: Thanks @Gh61 for a current answer!
This answer is no longer correct. lit-html 2.0+ has a static template function that accepts bindings in any position
The reason lit-html
doesn't allow for dynamic tag names is that lit-html works by replacing the expressions with special markers and then creating an HTML <template>
element with the result.
The key, and slightly subtle, part here is that it does not use the values to create the template. They are interpolated into the template after the template is cloned, which is after the HTML has ben parsed. There's no way to go into a tree of DOM and change the tag name of one element. We'd have to remove the element, replace it, set up any bindings, and move any children into the new element. This would be very expensive.
We do have plans to support static bindings (once we can drop support for older Edge browsers that don't implement template literals quite correctly) which are interpolated before creating the HTML <template>
, which would allow for using expressions for tag names. Static bindings would not be updatable with new data however - the value at template creation time is the only value used.
literal
and unsafeStatic
solutions. –
Altamirano For everyone interested in my solution: Use unsafeHTML
if you can (you should not do that if you wrap any input fields within).
import { unsafeHTML } from 'lit-html/directives/unsafe-html';
// ...
const template = `
<h${this.rank} class="a-heading">
<slot></slot>
</h${this.rank}>
`;
return html`
${unsafeHTML(template)}
`;
literal
or unsafeStatic
as shown in the other answer. –
Altamirano © 2022 - 2024 — McMap. All rights reserved.