Docs/Building applications

HTML templates

Keep presentation separate from data while rendering HTML in your application.

On this page

valk.template renders named templates at runtime. Register template contents, pass a typed data value to render, and handle a template error if rendering fails.

Render a small template#

This complete example keeps a template in a string:

Valk
use valk.template

class Page {
    title: String
}

fn main() {
    template.set_content("page.html", "<h1>{{ title }}</h1>")
    let html = template.render("page.html", Page { title: "Notes & ideas" }) ! {
        println("Could not render the page")
        return
    }
    println(html)
}

{{ title }} looks up the title field in the supplied data. By default, interpolated values are HTML-escaped, so the ampersand appears as &amp; in the rendered markup.

Move markup into files#

For an application with several views, keep templates in a directory and register their contents with:

Valk
template.set_content_many(#embed_dir("views"))

Template names are the paths relative to that directory. Embedding bundles the files into the executable, so changing one requires a rebuild. Rendering still happens at runtime; embedding does not validate every template expression during compilation.

Repeat and include#

A template can include another registered template and iterate over an array from its data:

HTML
@include("header.html")

<h1>{{ title }}</h1>
@each(notes as note)
<article>
    <h2>{{ note.title }}</h2>
    <p>{{ note.body }}</p>
</article>
@end

The supplied data should have a title and a notes array whose elements expose title and body. This keeps view structure in the template while application code decides which notes to render.

Conditions use @if(...), optional @elif(...) and @else, then @end.

Keep escaping intentional#

{{ value }} escapes its output. {! value !} inserts raw output, which is useful for HTML your application has already rendered and trusts. Raw insertion does not make arbitrary input safe to place in a page.

Treat template files as application code and pass user content as data. Do not concatenate user content into a new template source string.

Return the rendered page#

An HTTP handler can pass a successfully rendered string to http.Response.html(html). Decide how the handler should respond if rendering fails, rather than returning partial markup. See HTTP & networking for the handler structure.