Templates

Server-side rendering

In Alchemy, the Hawkejs template engine is used for rendering.

When a user visits a page for the first time, the appropriate templates will be generated on the server and sent to the browser. Subsequent navigations are then handled by Hawkejs and rendered by the browser.

Template syntax

Hawkejs templates are compiled into JavaScript functions on-the-fly. It doesn't treat the HTML source code as plain text, but rather converts it into a virtual DOM. Therefore, it's crucial to write valid HTML code.

For example, the following Hawkejs template is not valid:

<% tag_name = 'div' %><<% tag_name %>>Test</<% tag_name %>>

Directives

Hawkejs has special classes called Helpers, and these helpers can have methods that are made to change elements in a way.

One important example is the Router helper's directive. It is used to generate the correct href for an anchor:

<a
    !Route="Blogpost#view"
    +slug="my-slug">
    Go to my-slug post</a>

This will then be rendered into:

<a href="/my-slug">Go to my-slug post</a>

The !Route attribute invokes the applyDirective method of the Router helper, with Blogpost#view as an argument. The +slug attribute adds that value as a variable.

You can also use variables in place of literals:

<% my_route = 'Blogpost#view' %><% my_slug = 'my-slug' %>
<a
    !Route={% my_route %}
    +slug={% my_slug %}>
    Go to my-slug post</a>

Note that we do not write this as !Route="{% my_route %}". Although it would still work in this case, it explicitly casts the value to a string. There may be situations where you want the parameter to be a different type, and casting it to a string is not desired.

Variables

As previously mentioned, variables can be passed to a renderer from within a Controller:

StaticController.setAction(async function myAction(conduit) {
    let document = await this.getModel('Page').find('first');
    this.set('document', document);
    this.render('static/view_page');
});

After querying the database for the first Page, document will be an instance of Alchemy.Document.Page. However, when you access this variable within the view_page template, it will actually be an instance of Alchemy.Client.Document.Page.

Hawkejs automatically clones and converts all variables it sends to the renderer. If an instance has a toHawkejs() method, it will be used to handle the cloning. In Alchemy's case, the toHawkejs() method makes sure an instance of Alchemy.Client.Document is returned.