web-componenttemplate-literalslitlit-html

How to apply entire string as an attribute/prop to Lit web component?


I have a basic Text Lit web component with a red color for styling as such

import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";

@customElement("bb-text")
export class Text extends LitElement {
  render() {
    return html` <p style="color: red;"><slot></slot></p> `;
  }
}

I would like to pass the entire style attribute as a string like so

import { LitElement, html } from "lit";
import { customElement } from "lit/decorators.js";

function getStyle() {
  return 'style="color: red;"';
}

@customElement("bb-text")
export class Text extends LitElement {
  render() {
    return html` <p ${getStyle()}><slot></slot></p> `;
  }
}

What I have tried

  1. unsafeHTML: doesn't even render component

    return html` <p ${unsafeHTML(getStyle())}><slot></slot></p> `;
    
  2. custom directive: does nothing

    import { LitElement, html } from "lit";
    import { customElement } from "lit/decorators.js";
    import { Directive, directive } from "lit/directive.js";
    
    class StyleDirective extends Directive {
      render() {
        return 'style="color: red;"';
      }
    }
    const getStyle = directive(StyleDirective);
    
    @customElement("bb-text")
    export class Text extends LitElement {
      render() {
        return html` <p ${getStyle()}><slot></slot></p> `;
      }
    }
    

Lit's documentation on Element Expressions implies that it should be possible

html`<div ${myDirective()}></div>`

Solution

  • You need to use static expressions for that.

    import { html, unsafeStatic } from "lit/static-html.js";
    import { LitElement } from "lit";
    import { customElement } from "lit/decorators.js";
    
    function getStyle() {
      return 'style="color: red;"';
    }
    
    @customElement("bb-text")
    export class Text extends LitElement {
      render() {
        return html` <p ${unsafeStatic(getStyle())}><slot></slot></p> `;
      }
    }