Client-side templating

To avoid custom jQuery template building a slim client-side templating engine lit-html together with lit-element is used in the TYPO3 Core.

This templating engine supports conditions, iterations, events, virtual DOM, data-binding and mutation/change detections in templates.

Individual client-side templates can be processed in JavaScript directly using modern web technologies like template-strings and template-elements.

Rendering is handled by the AMD-modules lit-html and lit-element. Please consult the lit-html template-reference and the lit-element-guide for more information.

Examples

Variable assignment

import {html, render} from 'lit-html';

const value = 'World';
const target = document.getElementById('target');
render(html`<div>Hello ${value}!</div>`, target);
Copied!
<div>Hello World!</div>
Copied!

Unsafe tags would have been encoded (e.g. <b>World</b> as &lt;b&gt;World&lt;/b&gt;).

Conditions and iteration

import {html, render} from 'lit-html';
import {classMap} from 'lit-html/directives/class-map.js';

const items = ['a', 'b', 'c']
const classes = { list: true };
const target = document.getElementById('target');
const template = html`
   <ul class=${classMap(classes)}">
   ${items.map((item: string, index: number): string => {
      return html`<li>#${index+1}: ${item}</li>`
   })}
   </ul>
`;
render(template, target);
Copied!
<ul class="list">
   <li>#1: a</li>
   <li>#2: b</li>
   <li>#3: c</li>
</ul>
Copied!

The ${...} literal used in template tags can basically contain any JavaScript instruction - as long as their result can be casted to string again or is of type lit-html.TemplateResult. This allows to make use of custom conditions as well as iterations:

  • condition: ${condition ? thenReturn : elseReturn}
  • iteration: ${array.map((item) => { return item; })}

Events

Events can be bound using the @ attribute prefix.

import {html, render} from 'lit-html';

const value = 'World';
const target = document.getElementById('target');
const template = html`
   <div @click="${(evt: Event): void => { console.log(value); }}">
      Hello ${value}!
   </div>
`;
render(template, target);
Copied!

The result won't look much different than the first example - however the custom attribute @click will be transformed into an according event listener bound to the element where it has been declared.

Custom HTML elements

A web component based on the W3C custom elements ("web-components_") specification can be implemented using lit-element.

import {LitElement, html, customElement, property} from 'lit-element';

@customElement('my-element')
class MyElement extends LitElement {

 // Declare observed properties
 @property()
 value: string = 'awesome';

 // Avoid Shadow DOM so global styles apply to the element contents
 createRenderRoot(): Element|ShadowRoot {
   return this;
 }

 // Define the element's template
 render() {
   return html`<p>Hello ${this.value}!</p>`;
 }
}
Copied!
<my-element value="World"></my-element>
Copied!

This is rendered as:

<my-element value="World">
   <p>Hello world!</p>
</my-element>
Copied!