Vascula v0.1.5

Composition

{% render "name" %} renders another template, a child, in place. Use it for anything you would otherwise copy and paste: a product card, a price, an icon.

Template
<div class="grid">{% for p in settings.products %}{% render "card", product: p %}{% endfor %}</div>
Data
{
  "settings": {"products": [{"title": "Cup"}, {"title": "Saucer"}]},
  "children": {"card": {"source": "<article>{{ product.title }}</article>"}}
}
Output
<div class="grid"><article>Cup</article><article>Saucer</article></div>

#Arguments

Everything after the name is argument: value. Each argument becomes a variable in the child. Argument values are expressions, so filters work.

Template
{% render "price", currency: "EUR", amount: settings.cents | divided_by: 100 %}
Data
{
  "settings": {"cents": 1250},
  "children": {"price": {"source": "{{ amount }} {{ currency }}"}}
}
Output
12.5 EUR

A filter's own arguments continue after a comma, so a filtered value must be the last argument. Otherwise the filter takes the arguments that follow as its own:

Template
{% render "price", amount: settings.cents | divided_by: 100, currency: "EUR" %}
Data
{
  "settings": {"cents": 1250},
  "children": {"price": {"source": "{{ amount }} {{ currency }}"}}
}
Error
filter "divided_by" does not take a named argument "currency"

Put the filtered argument last, or assign it first and pass the variable.

An argument named settings or forloop, or a name the application reserves, is a compilation error. Passing the same argument twice is too.

#A child has its own scope

A child starts fresh. It sees:

  • its arguments,
  • its own settings, supplied by the application when it resolves the child,
  • the application's globals,
  • the data roots the application allows for the child.

It does not see the caller's variables, forloop, settings or data permissions. Whatever a child needs, pass it as an argument.

Template
{% assign secret = "caller only" %}{% render "child" %}
Data
{"children": {"child": {"source": "{{ secret }}"}}}
Error
undeclared name "secret"

Nothing flows back either: a child's assignments stay in the child, and break or continue in a child cannot end the caller's loop.

#Names are literal

The name after render must be a quoted string; a name computed from data is a compilation error. Inspection lists every template a template renders.

Template
{% render settings.which %}
Error
requires a literal template name

#How children are found

The application supplies the children: it maps each name to a compiled template, with that child's settings and data permissions (see Go API: children). An unknown name fails when the render tag runs, with the application's reason in the message.

#Limits

A child shares its caller's render budget: work, output and value limits cover the whole page, not each template. Children can render children, up to 32 levels deep, which stops a template that renders itself.

Next: Output and escaping.