Palette Templates use standard HTML <template> elements as their
source while compiling into an efficient, reactive Template instance.
The templating language for Palette is HTML. In fact, you can just use
<template> tags in your HTML and reference them when defining Components if
you prefer. It's pretty clean!
<template id="counting-button-template">
<button id="btn">
<span ::swap="$count"></span>
</button>
</template>
class CountingButton extends Component {
static template = document.getElementById("counting-button-template");
}
But if you want a little more oomph, you can use the html template string
helper to create template elements on the fly with a little bit of added sugar:
import { html } from "@rusticarcade/palette";
const template = html` <button id="btn">${"$count"}</button> `;
When using the html helper, any string inside of an interpolated value is
converted into a placeholder tag with a ::swap directive (more on that soon.)
Templates use custom HTML attribute directives prefixed with one or two colon
characters (:) to describe how the template should render with data.
The values of these directives must be a Notation, which is a string that describes what value to use in its place when the template renders.
Notations always begin with a special character, followed by a dot-separated accessor path.
There are four types of Notations, based on where you want to pull data from:
| Notation Prefix | Data Target | Example |
|---|---|---|
@ |
Host element attributes | @class, @content |
$ |
Reactive component state | $hidden, $user.name |
* |
Computed properties | *items.2.done, *classname |
# |
List item context | #id, #message.content |
Here's an example of binding a reactive state value to the "title" attribute of an element:
<a href="..." :title="$linkTitle">Click me!</a>
If our component then looks like...
class Example extends Component {
initialState = {
linkTitle: "I'm the link title!",
};
}
Then the rendered template content would be...
<a href="..." title="I'm the link title!">Click me!</a>
Whenever the Component updates it's state, the template will automatically update with the latest values.
In addition to the :attribute binding syntax, Palette supports several special
directives for more specific use cases:
| Directive | Use | Example |
|---|---|---|
::swap |
Swap the element for the target value | <span ::swap="$content" /> |
::each |
Render for each item in a list | <li ::each="*items" /> |
::key |
Define a key for list items | <li ::each="*items" ::key="#id" /> |
::tag |
Swap the tagname of this element | <h1 ::tag="*tagname">Title</h1> |
::swap DirectiveUsing ::swap="<notation>" causes the element with the directive to be replaced
with the value of the notation.
Strings, numbers, and booleans are cast to strings and rendered as text nodes.
HTMLElements are cloned and adopted to the DOM.
null and undefined render as an HTML comment.
Other values are unsupported.
::each and ::key DirectivesUsing ::each="<notation>" allows for iterating over a list of data. The notation
must resolve to a value that is an array of objects.
Properties on the array items can be accessed with the # notation prefix.
Along with ::each, you must specify a ::key directive. This directive must
contain a notation which resolves to a unique value for each element in the list.
Typically, the ::key will be something like #id, using a property called id
on the list item as the key.
class Example extends Component {
static template = html`
<ul>
<li ::each="*items" ::key="#id">
<span>The sky is ${"#color"}</span>
</li>
</ul>
`;
computedProperties = {
items: [
{
id: 1,
color: "red",
},
{
id: 2,
color: "blue",
}
]
}
}
::tag DirectivePretty simple: it just swaps out the html tag on the element with the directive.
It retains all child contents, but it does replace the target element itself.