<template is="literal-html">
A literal-html
template is replaced in the DOM with its own rendered content.
HTML <template>
s are allowed pretty much anywhere in a document, so
literal-html
templates enable you to freely mix islands of dynamically
rendered content into your HTML.
literal-html
Importing ./build/literal-html/module.js
from the repository
registers <template is="literal-html">
as a customised built-in template
element. (Support is polyfilled in Safari, who refuse to implement customised built-ins).
<script src="https://stephen.band/literal/build/literal-html/module.js" type="module"></script>
literal-html
templateWhere no src
or data
attribute is declared the template is rendered
immediately with an empty data
object. The rendered content replaces the
template in the DOM:
<template is="literal-html">
<p>${ events('pointermove', body).map((e) => round(e.pageX)) }px</p>
</template>
${ events('pointermove', body).map((e) => round(e.pageX)) }px
The src
attribute imports data from a JSON file or JS module. Imported data
is available inside the template as the data
object:
<template is="literal-html" src="../package.json">
<p>${ data.title }</p>
</template>
${ data.title }
A src
attribute pointing to a JS module imports the default export of that
module:
<template is="literal-html" src="../build/data/clock.js">
<p>${ data.time.toFixed(0) }</p>
</template>
${ data.time.toFixed(0) }
A named export can be imported using a fragment identifier:
<template is="literal-html" src="../data/cart.js#items">
<p>Items in cart: ${ data.length }</p>
<p>${ data.map((item) => `${ item.quantity } x ${ item.product.name }`).join(', ') }</p>
</template>
Items in cart: ${ data.length }
${ data.map((item) => `${ item.quantity } x ${ item.product.name }`).join(', ') }
data
across templatesImported data objects are cached. Other templates importing from the same
resource share the same data
object. Changes made to data
inside a template
are seen by all templates rendering that data:
<template is="literal-html" src="../package.json">
<label>Title (first template)</label>
<input type="text" value="${ bind('title', data) }" />
</template>
<template is="literal-html" src="../package.json">
<label>Title (second template)</label>
<input type="text" value="${ bind('title', data) }" />
</template>
Expressions can include()
other templates that are in the DOM by id. Included
templates need no special attributes but when included they are parsed as
Literal templates.
<template id="todo-li">
<li>${ data.text }</li>
</template>
<template is="literal-html">
<h5>Todo list</h5>
<ul>${ include('#todo-li', { text: 'Wake up' }) }</ul>
</template>
The include(src, data)
function is partially applicable, which is helpful for
mapping an array of objects to template includes:
<template is="literal-html" src="../data/todo.json">
<h5>Todo list</h5>
<ul>${ data.tasks.map(include('#todo-li')) }</ul>
</template>
Note that the included template #todo-li
is not removed from the DOM. It is
recommended to place templates intended as includes in the document <head>
.
If window.DEBUG = true
at time the element is registered, and the stylesheet
./build/debug.css
is imported, some debugging features are available. Compile
and render times are logged to the console. Open the console now to see compile
and render logs for the Literal templates on this page.
In addition a literal-html
template will render some error messages to the
DOM. If a literal-html
template cannot find src
data it is replaced with:
<template is="literal-html" src="../does-not-exist.json">
<h5>Not rendered</h5>
</template>
Where window.DEBUG
is not set, nothing is rendered. Frankly, error messaging
and could be improved, and maybe you could help.
More debugging information can be printed to the DOM using the print()
function:
<template is="literal-html" src="../data/cart.js#items">
${ print(data) }
</template>
Again, where window.DEBUG
is not set, nothing is rendered.
Turn a <time>
element into a clock face. Admittedly much of this example is
getting the CSS right, but the point it demonstrates is the suitability of
Literal for animating a bit of style:
<template id="clock-time">
<time class="clock" datetime="${ data.toISOString() }">
<span class="hour-clock-hand clock-hand" style="transform: rotate(${ 30 * (data.getHours() % 12) }deg);">${ data.getHours() } hours</span>
<span class="minute-clock-hand clock-hand" style="transform: rotate(${ 6 * (data.getMinutes() % 60) }deg);">${ data.getMinutes() } minutes</span>
<span class="second-clock-hand clock-hand" style="transform: rotate(${ 6 * (data.getSeconds() % 60) }deg);">${ data.getSeconds() } seconds</span>
</time>
</template>
<template is="literal-html">
${ clock(1).start().map(() => include('#clock-time', new Date())) }
</template>
Built by Stephen Band for Cruncher.
Documentation set in Euclid
and Martian Mono. Fonts
used for documentation not included as part of the license covering the
use of Literal
.