Table of contents
1.
Introduction
2.
Templates Syntax
2.1.
Syntax: the magic ‘@’ character
2.2.
Template parameters
2.3.
Template constructor
2.4.
Iterating
2.5.
If-blocks
2.6.
Declaring reusable blocks
2.7.
Declaring reusable values
2.8.
Import statements
2.9.
Comments
2.10.
Escaping
3.
Dependency Injection with Templates
4.
Common template use cases
4.1.
Layout
4.2.
Tags
4.3.
Includes
4.4.
moreScripts and moreStyles equivalents
5.
Support for a custom format to the template engine
5.1.
Overview of the templating process
5.2.
Implement a format
6.
Associate a file extension to the format
7.
Frequently Asked Questions
7.1.
What is the use of the Play framework?
7.2.
Is Play Framework MVC?
7.3.
How does the template engine determine which format a template file should be in? 
8.
Conclusion
Last Updated: Aug 13, 2025
Medium

Java developers-The Twirl template engine

Author Nagendra
0 upvote
Career growth poll
Do you think IIT Guwahati certified course can help you in your career?

Introduction

Play is a web framework for the JVM that deviates from the Servlet Specification. A Play Framework template functions similarly to a function that takes arguments from the template as input and outputs HTML code. Twirl is a Scala-based template engine included with Play whose design was influenced by ASP.NET Razor.
This blog describes Twirl's template engine in detail, including its template syntax, dependency injection using templates, typical use cases, and custom formats.

Without further ado, Let's get started.

Templates Syntax

A Play Scala template is a straightforward text file with discrete chunks of Scala code inside. Any text-based format, including HTML, XML, and CSV, can be produced by templates.
Front-end developers may utilise the template system with ease because it has been created to seem familiar to those used to dealing with HTML.
Following a straightforward naming strategy, templates are compiled as regular Scala functions. If a views/Application/index.scala.html template file is created, a views.html.Application.index class with a render() method will also be created. 

Consider the example:

Code:

@(customer: Customer, orders: List[Order])
<h1>Hello @customer.name!</h1>
<ul>
@for(order <- orders) {
  <li>@order.getTitle()</li>
}
</ul>
You can also try this code with Online Java Compiler
Run Code


Then, just as you would typically call a method on a class, you may call this from any Java code:

Code:

Content html = views.html.Application.index.render(customer, orders);
You can also try this code with Online Java Compiler
Run Code

Syntax: the magic ‘@’ character

The only special character in the Scala template is @. This character marks the start of a dynamic statement each time it appears. Your code will deduce the end of the dynamic statement. Thus you are not necessarily required to explicitly close the code block:

Code:

Hello @customer.getName()!
You can also try this code with Online Java Compiler
Run Code


This syntax only supports basic statements because the template engine uses code analysis to automatically determine when a code block ends. Use brackets to specifically indicate a multi-token statement if you want to put one:

Code:

Hello @(customer.getFirstName() + customer.getLastName())!
You can also try this code with Online Java Compiler
Run Code


Curly brackets can also be used to write a block of many statements:

Code:

Hello @{val name = customer.getFirstName() + customer.getLastName(); name}!
You can also try this code with Online Java Compiler
Run Code


@ is a special character, so occasionally, you'll need to escape it. Use @@ to accomplish this:

Code:

My email is abhinav@@example.com
You can also try this code with Online Java Compiler
Run Code

Template parameters

As a function, a template also requires arguments, which must be declared at the beginning of the template file:

Code:

@(customer: models.Customer, orders: List[models.Order])
You can also try this code with Online Java Compiler
Run Code


You can also set parameters to their default values:

Code:

@(title: String = "Home")
You can also try this code with Online Java Compiler
Run Code


You can also set several parameter categories:

Code:

@(title:String)(body: Html)
You can also try this code with Online Java Compiler
Run Code

Template constructor

A template is created by default as a static function that can be used anywhere. It might be simpler to inject your template with the components (and other templates) that it requires if it depends on other components, such as the messages API. Then you can easily inject that template into the controllers that need it.
Twirl enables declaring a constructor for templates at the beginning of the file, before the template arguments, using the @this() syntax. Similar to how template parameters are defined, the constructor arguments can also be defined:

Code:

@this(messagesApi: MessagesApi)
@(customer: models.Customer, orders: List[models.Order])
You can also try this code with Online Java Compiler
Run Code

Iterating

The for keyword can be used in the following very conventional way:

Code:

<ul>
@for(p <- products) {
  <li>@p.getName() ($@p.getPrice())</li>
}
</ul>
You can also try this code with Online Java Compiler
Run Code

If-blocks

If-blocks are common building blocks. Use the if statement found in Scala:

Code:

@if(items.isEmpty()) {
  <h1>Nothing to display</h1>
} else {
  <h1>@items.size() items!</h1>
}
You can also try this code with Online Java Compiler
Run Code

Declaring reusable blocks

Reusable code blocks are possible to make:

Code:

@display(product: models.Product) = {
  @product.getName() ($@product.getPrice())
}
<ul>
@for(product <- products) {
  @display(product)
}
</ul>
You can also try this code with Online Java Compiler
Run Code


You can also declare the reusable pure code blocks like follows:

Code:

@title(text: String) = @{
  text.split(' ').map(_.capitalize).mkString(" ")
}
<h1>@title("hello world")</h1>
You can also try this code with Online Java Compiler
Run Code


A reusable block defined with a name that begins with implicit will typically be labeled as implicit:

Code:

@implicitFieldConstructor = @{ MyFieldConstructor() }
You can also try this code with Online Java Compiler
Run Code

Declaring reusable values

Using the defining helper, you can declare scoped values:

Code:

@defining(user.getFirstName() + " " + user.getLastName()) { fullName =>
  <div>Hello @fullName</div>
}
You can also try this code with Online Java Compiler
Run Code

Import statements

Any content you like may be imported at the top of your template (or sub-template):

Code:

@(customer: models.Customer, orders: List[models.Order])
@import utils._
...
You can also try this code with Online Java Compiler
Run Code


Use root prefix in the import statement to resolve anything in an absolute manner.

Code:

@import _root_.company.product.core._
You can also try this code with Online Java Compiler
Run Code


You can declare common imports in build.sbt if you need them in all templates.

Code: 

TwirlKeys.templateImports += "org.abc.backend._"
You can also try this code with Online Java Compiler
Run Code

Comments

Using @* *@, you can add server-side block comments to templates.

Code:

@*********************
 * This is a comment *
 *********************@
You can also try this code with Online Java Compiler
Run Code


To describe your template in the Scala API doc, you can add a remark to the first line:

Code:

@*************************************
 * Home page.    					 *
 *									*
 * @param msg The message to display *
 *************************************@
@(msg: String)
<h1>@msg</h1>
You can also try this code with Online Java Compiler
Run Code

Escaping

Dynamic content portions are escaped in accordance with the rules of the template type (such as HTML or XML). Wrap a raw content fragment in the template content type if you want to output it.

For the code instance to produce raw HTML:

Code:

<p>
  @Html(article.content)
</p>
You can also try this code with Online Java Compiler
Run Code


Let's look into the details of dependency Injection.

Dependency Injection with Templates

Twirl templates can be created as classes rather than static objects by including a constructor at the top of the template using the special @this(args) syntax. As a result, Twirl templates may be directly injected into controllers and maintain their dependencies, avoiding the need for the controller to manage dependencies for both itself and the templates it must render.

As an illustration, let's say a template is dependent on the component Summarizer even though the controller doesn't use it:

Code:

public interface Summarizer {
  /** Provide a short form of string if over a certain length */
  String summarize(String item);
}
You can also try this code with Online Java Compiler
Run Code


Create the following file: app/views/IndexTemplate.scala.html using the @this constructor syntax:

Code:

@this(summarizer: Summarizer)
@(item: String)
@{summarizer.summarize(item)}
You can also try this code with Online Java Compiler
Run Code


Injecting the template into the constructor will define the controller in Play, concluding:

Code:

public class MyController extends Controller {
  private final views.html.IndexTemplate template;
  @Inject
  public MyController(views.html.IndexTemplate template) {
    this.template = template;
  }
  public Result index() {
    String item = "some extremely long text";
    return ok(template.render(item));
  }
}
You can also try this code with Online Java Compiler
Run Code

The controller can then have the template injected into it once the template has been defined along with its dependencies, but the controller is unaware of Summarizer.

You will need to manually add the @Inject annotation indicating that dependency injection should be used here if you use Twirl outside of a Play application:

Code:

TwirlKeys.constructorAnnotations += "@javax.inject.Inject()"
You can also try this code with Online Java Compiler
Run Code

This is pre-configured in a play application's default settings.

It's time to look into some Common template use cases.

Common template use cases

Because templates are just simple functions, you can create them however you like. Here are a few illustrations of some typical situations.

Layout

Let's create a template called views/main.scala.html that will serve as the main layout template:

Code: 

@(title: String)(content: Html)
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    <section class="content">@content</section>
  </body>
</html>
You can also try this code with Online Java Compiler
Run Code


As you can see, this template accepts a title and an HTML content block as its two inputs. From the another views/Application/index.scala.html template, we can now use it:

Code: 

@main(title = "Home") {
  <h1>Home page</h1>
}
You can also try this code with Online Java Compiler
Run Code


There are instances when you require a second page-specific content block, such as for a sidebar or breadcrumb trail. This can be achieved by adding the following parameter:

Code: 

@(title: String)(sidebar: Html)(content: Html)
<!DOCTYPE html>
<html>
  <head>
    <title>@title</title>
  </head>
  <body>
    <section class="content">@content</section>
    <section class="sidebar">@sidebar</section>
  </body>
</html>
You can also try this code with Online Java Compiler
Run Code


We have the following using our "index" template:

Code: 

@main("Home") {
  <h1>Sidebar</h1>

} {
  <h1>Home page</h1>
}
You can also try this code with Online Java Compiler
Run Code


As an alternative, we may declare the sidebar block independently:

Code: 

@sidebar = {
  <h1>Sidebar</h1>
}
@main("Home")(sidebar) {
  <h1>Home page</h1>
}
You can also try this code with Online Java Compiler
Run Code

Tags

Let's create a straightforward HTML notification using the views/tags/notice.scala.html tag:

Code: 

@(level: String = "error")(body: (String) => Html)

@level match {

  case "success" => {
    <p class="success">
      @body("green")
    </p>
  }

  case "warning" => {
    <p class="warning">
      @body("orange")
    </p>
  }

  case "error" => {
    <p class="error">
      @body("red")
    </p>
  }
}
You can also try this code with Online Java Compiler
Run Code


Let's utilise it now from a different template:

Code: 

@import tags._
@notice("error") { color =>
  Oops, something is <span style="color:@color">wrong</span>
}
You can also try this code with Online Java Compiler
Run Code

Includes

Again, nothing noteworthy about this. Any additional template you want to use (or, in fact, any other function, wherever it is specified) can be called by simply typing:

Code: 

<h1>Home</h1>
<div id="side">
  @common.sideBar()
</div>
You can also try this code with Online Java Compiler
Run Code

moreScripts and moreStyles equivalents

You can define a variable in the primary template in the following way to define the equivalents of older more scripts or moreStyles variables (as on Play! 1.x) in Scala:

Code: 

@(title: String, scripts: Html = Html(""))(content: Html)

<!DOCTYPE html>
<html>
    <head>
        <title>@title</title>
        <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
        <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
        <script src="@routes.Assets.at("javascripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
        @scripts
    </head>
    <body>
        <div class="navbar navbar-fixed-top">
            <div class="navbar-inner">
                <div class="container">
                    <a class="brand" href="#">Movies</a>
                </div>
            </div>
        </div>
        <div class="container">
            @content
        </div>
    </body>
</html>
You can also try this code with Online Java Compiler
Run Code


Additionally, a longer template that requires an additional script

Code: 

@scripts = {
    <script type="text/javascript">alert("hello !");</script>
}


@main("Title",scripts){
   Html content here ...
}
You can also try this code with Online Java Compiler
Run Code


Additionally, an enhanced template that doesn't require a separate script looks like this:

Code: 

@main("Title"){
   Html content here ...
}
You can also try this code with Online Java Compiler
Run Code


Let's look at the details of custom formats.

Support for a custom format to the template engine

Common template formats like HTML and XML are supported by the built-in template engine, but you may also add support for your own formats if necessary. 

Overview of the templating process

The static and dynamic content components of a template are added to create the final product by the template engine. Think about the following example template:

Code: 

foo @bar baz
You can also try this code with Online Java Compiler
Run Code


It is made up of one dynamic part and two static parts (foo and baz) and (bar). These components are combined by the template engine to create the final product. Actually, the value of the bar can be escaped before being concatenated with the remainder of the output to prevent cross-site scripting attacks. Each format has a different escape procedure; for example, in HTML, you want to change "<" into "&it."
In conclusion, you must carry out the following actions in order to support your own template format:

  • Create the text integration procedure for the format
     
  • Assign the format a file extension.

Implement a format

Put the play.twirl.api to use. The methods A escape(String text) and A raw(String text) of the Format <A> interface will be used to combine the static and dynamic template components, respectively. The type component The result type of the template rendering is defined by the format's letter A, for example, Html for an HTML template. The play.twirl.api.Appendable <A> trait, which specifies how to concatenate parts together, must be a subtype of this type. 
Play has a play.twirl.api.BufferedContent<A> abstract class for convenience, which implements play.twirl.api.Appendable<A> and implements the play.twirl.api.Content interface so Play understands how to serialise it as an HTTP response body.
To put it briefly, you must create two classes: one that defines the outcome (by implementing play.twirl.api.Appendable<A>) and another that defines the text integration process (by implementing play.twirl.api.Format<A>). For instance, the HTML format could be described as follows:

Code:

public class Html extends BufferedContent<Html> {
  public Html(StringBuilder buffer) {
    super(buffer);
  }
  String contentType() {
    return "text/html";
  }
}

public class HtmlFormat implements Format<Html> {
  Html raw(String text: String) { … }
  Html escape(String text) { … }
  public static final HtmlFormat instance = new HtmlFormat();
}
You can also try this code with Online Java Compiler
Run Code


Let's look at the details of associating a file extension to the format.

Associate a file extension to the format

Just before assembling the entire application sources, the build process converts the templates into a.scala files. A sbt setting of the type Map[String, String] defines the mapping between file extensions and template formats in the TwirlKeys.templateFormats key. For instance, in order to link the .scala.html files to your unique my.HtmlFormat format and have Play use it, you must include the following in your build file:

Code:

TwirlKeys.templateFormats += ("html" -> "my.HtmlFormat.instance")
You can also try this code with Online Java Compiler
Run Code

Frequently Asked Questions

What is the use of the Play framework?

Scala & Java developers may create web applications quickly and easily with Play Framework. Play's architecture is lightweight, stateless and suitable for the web. Play gives highly scalable applications predictable and low resource consumption (CPU, memory, threads).

Is Play Framework MVC?

Yes, the Open-source web application framework Play Framework uses the model-view-controller (MVC) design principle.

How does the template engine determine which format a template file should be in? 

It examines the file's extension; if it ends in .scala.html, the HTML format is connected to the file.

Conclusion

In this article, we have extensively discussed the details of the Twirl template engine along with the details of its template syntax, dependency Injection with Templates, Common use cases, and custom formats.

We hope that this blog has helped you enhance your knowledge regarding the Twirl template engine, and if you would like to learn more, check out our articles on Java. You can refer to our guided paths on the Coding Ninjas Studio platform to learn more about DSADBMSCompetitive ProgrammingPythonJavaJavaScript, etc. To practice and improve yourself in the interview, you can also check out Top 100 SQL problemsInterview experienceCoding interview questions, and the Ultimate guide path for interviews. Do upvote our blog to help other ninjas grow. Happy Coding!!

Live masterclass