Crinja Templates

Azu uses Crinja a powerful template engine built for the Crystal Language

,Templates::Renderable will define a private function named render(template : String, data) with one clause per file system template.

 class Dashboard::IndexPage
    include Response
    include Templates::Renderable
    
    TEMPLATE = "dashboard/index.jinja"
    
    getter joobq = JoobQ.statistics

    def render
      render TEMPLATE, {
        "busy"                  => ProcessingCounter.mount,
        "latency"               => LatencyCounter.mount,
        "counts"                => counts[:busy],
        "processing_chart_data" => {data: processing}.to_json,
        "processing_status"     => ProcessingChart.mount,
        "queue_table"           => QueuesTable.mount,
      }
    end
  end

Template Syntax

The following is a quick overview of the template language to get you started.

More details can be found in the template guide. The original Jinja2 template reference can also be helpful, Crinja templates are mostly similar.

Expressions

In a template, expressions inside double curly braces ({{ ... }}) will be evaluated and printed to the template output.

Assuming there is a variable name with value "World", the following template renders Hello, World!.

Hello, {{ name }}!

The properties of an object can be accessed by a dot (.) or square brackets ([]). Filters modify the value of an expression.

Hello, {{ current_user.name | default("World") | titelize }}!

Tests are similar to filters but are used in the context of a boolean expression, for example as a condition of an if tag.

{% if current_user is logged_in %}
  Hello, {{ current_user.name }}!
{% else %}
  Hey, stranger!
{% end %}

Tags

Tags control the logic of the template. They are enclosed in {% and %}.

{% if is_morning %}
  Good Morning, {{ name }}!
{% else %}
  Hello, {{ name }}!
{% end %}

The for tag allows looping over a collection.

{% for name in users %}
  {{ user.name }}
{% endfor %}

Other templates can be included using the include tag:

{% include "header.html" %}

<main>
  Content
</main>

{% include "footer.html" %}

Macros

Macros are similar to functions in other programming languages.

{% macro say_hello(name) %}Hello, {{ name | default("stranger") }}!{% endmacro %}
{{ say_hello('Peter') }}
{{ say_hello('Paul') }}

Template Inheritance

Template inheritance enables the use of block tags in parent templates that can be overwritten by child templates. This is useful for implementing layouts:

{# layout.html #}

<h1>{% block page_title %}{% endblock %}</h1>

<main>
  {% block body %}
    {# This block is typically overwritten by child templates #}
  {% endblock %}
</main>

{% block footer %}
  {% include "footer.html" %}
{% endblock %}
{# page.html #}
{% extends "layout.html" %}

{% block page_title %}Blog Index{% endblock %}
{% block body %}
  <ul>
    {% for article in articles if article.published %}
    <div class="article">
      <li>
        <a href="{{ article.href | escape }}">{{ article.title | escape }}</a>
        written by <a href="{{ article.user.href | escape}}">{{ article.user.username | escape }}</a>
      </li>
    {%- endfor %}
  </ul>
{% endblock %}

Last updated