Thursday, March 3, 2016

Handlebars

I personally prefer the logicless templates, so mustache simply The Best for me.  Unfortunately, the real world is not so simple,  therefore, I use handlebars.

Paly itself prefer Twirl. Well, it's a good thing, but I still like handlebars much more.

Fortunately,  we can use handlebars as the template engine in Play. You can find some ready to use plugins on the GitHub, like play2-handlebars. And you can easily use the original handlebars.java library by yourself. I stick with the last option. It's easy and you can always update handlebars to the last version without depending on other plugins.

It's a good idea to use a separate folder for the templates. Assume you create the templates folder in the project root. Then you will need to add two new instructions to the build.sbt file.
// Add the handlebars library
libraryDependencies += "com.github.jknack" % "handlebars" % "4.0.3"

// Copy handlebars templates to the production
mappings in Universal ++=
  (baseDirectory.value / "templates" * "*" get) map
    (x => x -> ("templates/" + x.getName))
The last thing just to use the handlebars engine. I extend trivial controller class from the play-java framework.
package controllers;

import java.io.File;
import java.util.HashMap;
import java.util.Map;

import javax.inject.Inject;

import com.github.jknack.handlebars.Handlebars;
import com.github.jknack.handlebars.Template;
import com.github.jknack.handlebars.io.FileTemplateLoader;
import com.github.jknack.handlebars.io.TemplateLoader;
import com.google.common.collect.ImmutableMap;

import play.Environment;
import play.mvc.Controller;
import play.mvc.Result;

public class Application extends Controller {

  // We need an environment to get the template folder
  @Inject
  private Environment environment;
 
  public Result index() throws Exception {
     
    // The data
    Map data = new HashMap<>();
    data.put("title", "Page Title");
    data.put("header", "Header");
    data.put("main", ImmutableMap.of("article", "Main Article"));
    data.put("footer", "Footer");
     
    // Get the template folder
    File rootFolder = environment.getFile("/templates");

    // Put the ".hbs" as a template extension.
    TemplateLoader loader = new FileTemplateLoader(rootFolder, ".hbs");
        
    // Initialize the engine
    Handlebars handlebars = new Handlebars(loader);
        
    // Compile the "templates/page.hbs" template
    Template template = handlebars.compile("page");
     
    // Fill it with data
    String page = template.apply(data);
        
    // Return the page to the client
    return ok(page).as("text/html");
  }

}
Yea, here is the template:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>{{title}}</title>
    <meta name="description" content="{{description}}">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <header>
        {{header}}
    </header>
    <main>
     <article>
        {{main.article}}
     </article>
    </main>
    <footer>
        {{footer}}
    </footer>
</body>
</html>
And the result:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Page Title</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <header>
        Header
    </header>
    <main>
     <article>
        Main Article
     </article>
    </main>
    <footer>
        Footer
    </footer>
</body>
</html>

1 comment: