Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Handlebars templating

Handlebars

Quick start - unregistered template

  • Handlebars

  • render_template

  • json

  • Handlebars is templating language implemented in Rust. It is based on the ideas of the original HandlebarsJS but it is not 100% compatible.

  • We have a very simple template embedded in our Rust code. It has one placeholder {{name}}.

  • We pass a JSON string to the render_template function.

use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;

fn main() {
    match render() {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render() -> Result<(), Box<dyn Error>> {
    let reg = Handlebars::new();
    println!(
        "{}",
        reg.render_template("Hello {{name}}", &json!({"name": "foo"}))?
    );

    Ok(())
}
  • The generated output looks like this:
Hello foo

[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"

Quick start - registered template

  • register_template_string

  • render

  • In this example we register a template to make it easier to reuse it and then use it twice.

use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;

fn main() {
    match render() {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render() -> Result<(), Box<dyn Error>> {
    let mut reg = Handlebars::new();
    reg.register_template_string("tpl_1", "Good afternoon, {{name}}")?;

    println!("{}", reg.render("tpl_1", &json!({"name": "foo"}))?);
    println!("{}", reg.render("tpl_1", &json!({"name": "bar"}))?);

    Ok(())
}
Good afternoon, foo
Good afternoon, bar

[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"

Handlebars - render to file

  • In some cases we would like to save the generated string in a file.
use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;
use std::fs::File;
use std::io::Write;

fn main() {
    match render_without_register("hello.html") {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render_without_register(filename: &str) -> Result<(), Box<dyn Error>> {
    let reg = Handlebars::new();
    let html = reg.render_template("Hello {{name}}", &json!({"name": "foo"}))?;
    let mut file = File::create(filename).unwrap();
    writeln!(&mut file, "{}", html).unwrap();

    Ok(())
}
Hello foo
[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"

Handlebars - read template from file

  • We have a separate function to read the content of the template file.
Hello {{name}} from the template file.
use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::io::Write;

fn main() {
    let filename = "hello.html";
    let template = "template.html";
    match render_without_register(template, filename) {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render_without_register(template_file: &str, filename: &str) -> Result<(), Box<dyn Error>> {
    let template = read_template(template_file);

    let reg = Handlebars::new();
    let html = reg.render_template(&template, &json!({"name": "foo"}))?;

    let mut file = File::create(filename).unwrap();
    writeln!(&mut file, "{}", html).unwrap();

    Ok(())
}

fn read_template(template_file: &str) -> String {
    let mut template = String::new();
    match File::open(template_file) {
        Ok(mut file) => {
            file.read_to_string(&mut template).unwrap();
        }
        Err(error) => {
            println!("Error opening file {}: {}", template_file, error);
        }
    }
    template
}
Hello foo from the template file.

[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"

Handlebars - show time of generation

use chrono::{DateTime, Utc};
use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::io::Write;

fn main() {
    let filename = "hello.html";
    let template = "template.html";
    match render_without_register(template, filename) {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render_without_register(template_file: &str, filename: &str) -> Result<(), Box<dyn Error>> {
    let template = read_template(template_file);

    let utc: DateTime<Utc> = Utc::now();

    let reg = Handlebars::new();
    let html = reg.render_template(&template, &json!({"utc": format!("{}", utc)}))?;
    let mut file = File::create(filename).unwrap();
    writeln!(&mut file, "{}", html).unwrap();

    Ok(())
}

fn read_template(template_file: &str) -> String {
    let mut template = String::new();
    match File::open(template_file) {
        Ok(mut file) => {
            file.read_to_string(&mut template).unwrap();
        }
        Err(error) => {
            println!("Error opening file {}: {}", template_file, error);
        }
    }
    template
}
Hello. This page was generated at {{utc}}.
Hello. This page was generated at 2023-10-08 12:17:47.976870543 UTC.

[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"
chrono = "0.4.26"

Handlebars loop (each) on array

<h1>Fruits</h1>

<ul>
{{#each fruits as |fruit|}}
  <li>{{fruit}}</li>
{{/each}}
</ul>

<h1>Fruits</h1>

<ul>
  <li>apple</li>
  <li>banana</li>
  <li>peach</li>
</ul>


use handlebars::Handlebars;
use serde_json::json;
use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::io::Write;

fn main() {
    let filename = "hello.html";
    let template = "template.html";
    match render_without_register(template, filename) {
        Ok(_) => println!(),
        Err(_) => println!("error"),
    }
}

fn render_without_register(template_file: &str, filename: &str) -> Result<(), Box<dyn Error>> {
    let mut template = String::new();
    match File::open(template_file) {
        Ok(mut file) => {
            file.read_to_string(&mut template).unwrap();
        }
        Err(error) => {
            println!("Error opening file {}: {}", template_file, error);
        }
    }

    let reg = Handlebars::new();
    let fruits = ["apple", "banana", "peach"];
    let html = reg.render_template(&template, &json!({"fruits": fruits}))?;
    let mut file = File::create(filename).unwrap();
    writeln!(&mut file, "{}", html).unwrap();

    Ok(())
}
[package]
name = "handlebars-quick"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
handlebars = "4.3.7"
serde_json = "1.0.97"