Files
cms-core/Documentation/Changelog/11.0/Feature-91810-IntroduceLit-htmlAndLit-elementAsClient-sideTemplatingEngine.rst

167 lines
4.4 KiB
ReStructuredText

.. include:: /Includes.rst.txt
.. _feature-91810:
=====================================================================================
Feature: #91810 - Introduce lit-html and lit-element as client-side templating engine
=====================================================================================
See :issue:`91810`
Description
===========
To avoid custom jQuery template building a new slim client-side templating
engine lit-html_ together with lit-element_ is introduced. The modules
are available via the umbrella javascript module `lit`.
This templating engine supports conditions, iterations, events, virtual DOM,
data-binding and mutation/change detections in templates.
.. _lit-html: https://lit-html.polymer-project.org/
.. _lit-element: https://lit-element.polymer-project.org/
Impact
======
Individual client-side templates can be processed in JavaScript directly
using modern web technologies like template-strings_ and template-elements_.
.. _template-strings: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals
.. _template-elements: https://developer.mozilla.org/de/docs/Web/HTML/Element/template
Rendering is handled by the AMD-modules `lit-html` and `lit-element`.
Please consult the `lit-html` template-reference_ and lit-element-guide_ for more
information.
.. _template-reference: https://lit-html.polymer-project.org/guide/template-reference
.. _lit-element-guide: https://lit-element.polymer-project.org/guide
Examples
========
Variable assignment
-------------------
.. code-block:: ts
import {html, render} from 'lit';
const value = 'World';
const target = document.getElementById('target');
render(html`<div>Hello ${value}!</div>`, target);
.. code-block:: html
<div>Hello World!</div>
Unsafe tags would have been encoded (e.g. :html:`<b>World</b>`
as :html:`&lt;b&gt;World&lt;/b&gt;`).
Condition and iteration
-----------------------
.. code-block:: ts
import {html, render} from 'lit';
import {classMap} from 'lit/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);
.. code-block:: html
<ul class="list">
<li>#1: a</li>
<li>#2: b</li>
<li>#3: c</li>
</ul>
The :js:`${...}` 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.TemplateResult`. This allows to
make use of custom conditions as well as iterations:
* condition: :js:`${condition ? thenReturn : elseReturn}`
* iteration: :js:`${array.map((item) => { return item; })}`
Events
------
Events can be bound using the `@` attribute prefix.
.. code-block:: ts
import {html, render} from 'lit';
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);
The result won't look much different from the first example - however the
custom attribute :html:`@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 the `LitElement` base class.
.. code-block:: ts
import {LitElement, html} from 'lit';
import {customElement, property} from 'lit/decorators';
@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>`;
}
}
.. code-block:: html
<my-element value="World"></my-element>
This is rendered as:
.. code-block:: html
<my-element value="World">
<p>Hello world!</p>
</my-element>
.. _web-components: https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements
.. index:: Backend, JavaScript, ext:backend