Template literal

The template solution is part of the NPM package @tmorin/ceb-templating-literal.

The built-in template solution provides an API to express templates based on Template literal. The API is the Tagged Templates html.

Common usages

Text

Write the content Hello, World! in the <p> element:

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const name = "World"

const template: Template = html`<p>Hello, ${name}!</p>`

template.render(document.body)

Attribute

Set the value foo to the attribute bar:

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const foo = "bar"

const template: Template = html`<input class="${foo}" />`

template.render(document.body)

Set boolean values, the checked attribute won't be rendered because its value is false:

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const checked = false

const template: Template = html`<input
  required
  disabled=""
  checked="${checked}" />`

template.render(document.body)

Property

Set the value foo to the property bar:

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const value = "Foo"

const template: Template = html`<input p:bar="${value}" />`

template.render(document.body)

Prevent extra processing

The special attribute o:skip, notifies the template engine that the children of the element should not be processed.

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const template: Template = html`<div><ul o:skip></ul></div>`

template.render(document.body)

When rendering within a Shadow DOM, the usage of the element <slot> have the same effect: the children of the slot element won't be processed.

Optimize patch activities

The special attribute o:key, notifies the template engine that the current node can be identified by a key. The key can be of any types.

The feature should be used when rendering a dynamic list where the items can be added/removed/shift. For each item, the o:key should be provided. So that, the engine will be able to efficiently discover the related DOM nodes.

import { Template } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

const lis = ["item A", "item B"].map(
  (item) => html`<li o:key="${item}">${item}</li>`
)

const template: Template = html`<div>
  <ul>
    ${lis}
  </ul>
</div>`

template.render(document.body)

When rendering within a Shadow DOM, the usage of the element <slot> have the same effect: the children of the slot element won't be processed.

Grey DOM

The special element <ceb-sot></ceb-slot> is the marker of the placeholder.

Given the following Custom Element with template expressed using the literal approach:

import { ElementBuilder } from "@tmorin/ceb-elements-core"
import { Template, TemplateBuilder } from "@tmorin/ceb-templating-builder"
import { html } from "@tmorin/ceb-templating-literal"

class HelloWorld extends HTMLElement {
  render(): Template {
    return html`<p>Hello, <ceb-slot></ceb-slot>!</p>`
  }
}

ElementBuilder.get().builder(TemplateBuilder.get().grey()).register()

When the following statement is created and rendered:

<hello-worlder>John Doe</hello-worlder>

Then the Light DOM becomes:

<hello-worlder>
  Hello, <ceb-slot>John Doe<ceb-slot>!
</hello-worlder>