Template

The Template CPart allow components to render their HTML content using a tiny domain-specific language, called the Modulo Templating Language.

Without a Template CPart (or equivalent custom code), the default behavior of the Component CPart is to make no attempt to alter their contents. However, most components require complicated HTML structures within them. This is where Templates come into play: They generate the innerHTML of a component.

Templates are not DOM-based, but instead render synchronously to a String during the render lifecycle phase, and store the results in renderObj.component.innerHTML. The Component CPart will read this HTML code during the reconcile phase and then "reconcile", modify it's contents to resemble the target innerHTML. (More on this is in the Component CPart documentation above.)

Every time a Component renders, the Template will render using the renderObj as a "template context", or, in other words, using the various CPart's contributions to the renderObj as Template variables that can be inserted into the HTML.

Templating reference

See the Templating documentation for further information on the functionality of the Templating CPart.

Example Usage

Example #1: Simple template

<Template> {# Code in this format is a comment #} {# Use state variables such as "state.count" as such #} <p>The count is: <em>{{ state.count }}</em></p> {# Using a |filter we can modfiy data on the fly #} <p>The next count is: <em>{{ state.count|add:1 }}</em></p> {# Using a "template tag" we check value #} {% if state.count gt 9 %} <p>The count has reached 10!</p> {% endif %} </Template> <State count:=42 ></State>

Example #2: Complex template

<Template> <p>There are <em>{{ state.count }} {{ state.count|pluralize:"articles,article" }}</em>.</p> {# Show the articles #} {% for article in state.articles %} <h4 style="color: blue">{{ article.headline|upper }}</h4> {% if article.tease %} <p>{{ article.tease|truncate:30 }}</p> {% endif %} {% endfor %} </Template> <!-- The data below was used to render the template above --> <State count:=42 articles:='[ {"headline": "Modulo released!", "tease": "The most exciting news of the century."}, {"headline": "Can JS be fun again?"}, {"headline": "MTL considered harmful", "tease": "Why constructing JS is risky business."} ]' ></State>

Example #3: Multiple templates with include

Note that in a full example, you might consider loading all or some Templates using a -src= attribute, so you can edit the HTML files separately.

Also note that in mutli-template components, one should have no name (or have active:=true).

<Template -name="header"> <p><strong>{{ state.title }}</strong></p> </Template> <Template -name="body"> {% for para in state.paras %} <p>{{ para }}</p> {% endfor %} </Template> <Template> <div class="container"> <section> <article> <div> {% include header %} </div> <main> {% include body %} </main> <article> </section> </div> </Template> <State title="Multi-Template World" paras:='[ "A b c", "1 2 3", "Do re mi", "Togeprrrrri" ]' ></State> <Style> .container { border: 1px solid gray; margin: 5%; padding: 5%; background: white; box-shadow: 5px 5px 5px #00000033; } section, article, main, div, p { margin: 1%; padding: 1%; box-shadow: 0 0 2px #ff000033; } </Style>

Example #4: Multiple templates, chosen with slider

<Template -name="template_a"> <h1>First template</h1> <p>AAA</p> </Template> <Template -name="template_b"> <h1>The second include</h1> <p>BBB</p> </Template> <Template -name="template_c"> <h1>Final Include</h1> <p>CCC</p> </Template> <Template> <input [state.bind] name="val" type="range" min="1" max="3" step="1" /> {% if state.val is 1 %} {% include template_a %} {% elif state.val is 2 %} {% include template_b %} {% else %} {% include template_c %} {% endif %} </Template> <State val:=1 ></State>

Example #4: Style templates

By defining a <style Template>, can use the Modulo templating language to apply "templating" to CSS:

<Template> <section style="display: grid; grid-template-columns: 1fr 2fr"> <label>Color</label> <input [state.bind] name="bg" type="color" /> {% for key, value in state.shape %} <label>{{ key|capfirst }}</label> <input [state.bind] name="shape.{{ key }}" type="range" min="1" max="50" /> {% endfor %} </section> <div style="{% include div_style %}">LOREM IPSUM</div> <pre>div { {% include div_style %} }</pre> </Template> <style Template -filter-content="trim:'x {,}'" -name="div_style"> x { color: white; background-color: {{ state.bg }}; {% for key, value in state.shape %} {{ key }}: {{ value }}px; {% endfor %} } </style> <State bg="#308330" shape:={} shape.width:=50 shape.height:=30 shape.padding:=5 shape.margin:=2 ></State>

Note the following two unusual aspects of this example. Both of these are optional, but only intended to make the CPart easier to read, and for editors to automatically apply syntax highlighting as expected.

  • Observe how in the example below we use -filter-content= in order to "trim" away our placeholder CSS (x { ... }). This makes editing this Template CPart easier to read, since it will follow standard <style> syntax rule, thus the x just functioning as a purely cosmetic placeholder element.

  • Observe how we use this dual tag format (<style Template>). To Modulo, this is the same as doing <Template>. However, using a style tag makes it easier to read, and syntax highlighting will work automatically. Thus, in this case we can use the Modulo feature that lets the first attribute instead determine the CPart name instead of the actual tag name.