Twirl

Twirl is the Play 2 templating language.

Please note that the example for this guide needs to be updated to work with Scalatra 2.3.x / Scala 2.11.x.

Evaluating Twirl

While the Scalatra developer generally prefer Scalate for server-side templating, Twirl provides an interesting alternative.

Advantages of Twirl

  • Templates are rendered by simply calling a generated render function with the correct arguments. Since this call can be made from other templates, the artificial distinction between “layouts” and “views” is erased.
  • Twirl simply embeds Scala in arbitrary text, whether that text is HTML, JSON, XML, or anything else. There is no new language to learn.
  • When you use Twirl, the compiler can check type errors within a template, but unlike Scalate it can also check that templates are being passed the right parameter types.

Disadvantages of Twirl

  • Play 2 is legendary for its slow compile times, and the code Twirl produces is a major offender in that regard. If your project involves many templates, compile times will get progressively worse.
  • Since Twirl is a general-purpose template languages, it is not nearly as DRY as Scalate’s Scaml or Jade languages for HTML/XML templates.
  • There is no tooling support for Twirl. Get ready to hit the space and tab keys often.
  • Twirl makes some undocumented rendering decisions with respect to certain types (see below).

Using Twirl

Installation

addSbtPlugin("io.spray" % "sbt-twirl" % "0.6.1")
  • Enable the plugin in build.sbt:
seq(Twirl.settings: _*)

Usage

You add your templates to src/main/twirl. Twirl files are of the form [name].scala.[format]. For example, foo.scala.html or bar.scala.xml. The package of the generated Scala file will follow the name of the template file, and its path.

For example, if you create a file src/main/twirl/com/example/myTwirlTemplate.scala.html, the resulting Scala file will be in the package com.example.html.

You can call it with:

com.example.html.myTwirlTemplate.render(param1, param2, ...)

A basic example

Create src/main/twirl/org/scalatra/example/hello.scala.html with:

@(date: java.util.Date)

<html>
  <body>
    <h1>Twirl reporting for duty at @date.toString!</h1>
  </body>
</html>

Now render it in src/main/scala/org/scalatra/example/TwirlApp.scala with:

package org.scalatra.example

import org.scalatra._

class TwirlApp extends ScalatraServlet {

  get("/") {
    html.helloTwirl.render(new java.util.Date)
  }
}

Your result?

Full usage guide

We have only provided a taste of what Twirl can do. Since it’s an external project, we encourage you to also consult the official documentation.

The sbt plugin’s README also has a useful syntax summary.

Rendering oddities

There are some undocumented conversions Twirl initiates before rendering. Beware!

Consider this template:

@()

Twirl makes some special decisions in rendering certain types, including:

<ul>

  <li>
    Collections like
    <ul>
      <li><code>List</code>: @List("first", "second", "third")</li>
      <li><code>Seq</code>: @Seq("first", "second", "third")</li>
    </ul>
  </li>
  <li>
    <code>Option</code>
    <ul>
      <li><code>Some</code>: @Some("foo")</li>
      <li><code>None</code>: @None</li>
    </ul>
  </li>
  <li>
    But not <code>Either</code>
    <ul>
      <li><code>Left</code>: @Left("foo")</li>
      <li><code>Right</code>: @Right("bar")</li>
    </ul>
  </li>
  <li>
    Others?
  </li>
</ul>

It will render as: