Chapter 3. Templating Easily with Scala

Play! Framework 2 is a web framework, and so is meant to create web applications. A web application is an application that presents an interactive interface through a web browser. But the browser might not be the only client of such an application, because data created while using it could be used by other applications (that's web integration). And so, very often, the server side of a web application is also exposing data through web services. Which leads us to the need, as developers, to not only generate HTML pages, but also TXT pages, XML pages, and so on.

Play! 2 provides a powerful way to create all such external representations of server-side data: a type-safe templating system based on Scala.

In this chapter, we'll cover the following topics:

  • Understanding exactly what a template is
  • Looking at where and how they are declared
  • Creating a reusable HTML template
  • Combining dynamic data with templates
  • What Play! 2's compiler will generate
  • How to combine several templates into a single one (layout)
  • How to skin templates

Shape it, compose it, re-use it

This first section will concentrate on what a template is, its structure, and its features. We'll see how it can help us to easily create views in a composable and sharable fashion.

Creating our first template

A template in Play! Framework 2 is basically a file with a specific extension that commonly resides under the views package. So, a template filename always has the following pattern:

<template-name>.scala.<content-type>

It is composed of the following:

  • A template name, which must be formatted like a variable (for example, listContainer). This will be used to reference it in the controllers.
  • A first extension part, .scala, which is always the same. As stated earlier, templates are Scala-based.
  • A second extension part, which is the real type of the data. Out of the box types are .html, .xml, and .txt, but Play! 2 is extensible enough to enable us to add new ones.
    Creating our first template

Play! 2 will detect these files based on the pattern and will compile them into functions that will be available for the controllers or other templates.

Note

While the structure was rigid in Play! 1, this new version enables us to create our files wherever we want. But views is a good convention—to have everything in one place. However, files still have to match the pattern.

So let's create a new template named listContainer that renders HTML content.

Structuring it

A template is expected to respect a certain structure that starts with the parameters list . As a template will be compiled into a function, it can accept parameters just as any other function in Scala.

When declaring a Scala function, we need to first give it a name—the filename is the function name—and only then can we declare its parameters. So, logically, this is the first line of all templates.

These parameters are declared in exactly the same way as for Scala functions—that is, between parentheses and paired by the name and type separated with a colon—as shown in the following screenshot:

Structuring it

The only thing that differs is that we need to use the magic character (@), because it's Scala code in a template. To illustrate this, we'll add two parameters to our listContainer template.

It's pretty easy. We've just defined our template as a function that takes the following two parameters:

  • level: It is of type Int
  • items: A sequence containing strings

At this stage, the Play! 2 compiler will make available to us a function with the following signature:

def function(level:Int, items:Seq[String]):Html

Play! 2 has worked out that the file is an HTML template, from the second extension (.html) of the template name—that is, the Html result type of the function.

Adding content

Now that we have created a template with its parameters, we will define a function that produces HTML, but an empty one!

The content of a template is inserted into the file directly after the parameters' declaration.

In our case, we're about to create an HTML structure using HTML notation (the same happens for JSON, XML, and so on). So let's create some content in there:

Adding content

Now, the listContainer function will produce a small HTML instance of this simple excerpt.

Wait! It's not really useful, because it does nothing with our parameters. That's where Chapter 2, Scala – Taking the First Step, comes to our rescue. We'll use Scala to create some relevant content based on the server-side data.

Adding content

As you can see, we adapted the template to use the level parameter—which is of the type Int—to change the flow for both the title and the list of rendered items. We used it to change the header level (h1, h2, and so on) and to adapt the style attribute.

Then we used the map function on Seq to produce a new sequence of HTML blocks, each of them being the representation of an item.

Composing templates

In order to see our listContainer template in action, we could define an action and a route that asks to render it; but what we'll do instead is call this template in our index.scala.html template. That's how layout is achieved in Play! 2. See the following screenshot:

Composing templates

The previous screenshot shows how to call a template from within another one, which is basically calling a function from within another function.

Note

The screenshot also shows the action that must render the index page; it has been covered in Chapter 1, Getting Started with Play! Framework 2.

So the index.scala.html template/function is first declaring a single parameter message, followed by its body/definition that starts by using the main function with two parameter blocks.

  • The first parameter is for the title
  • The second parameter is actually a block of code that is enclosed within curly braces

    Note

    Actually, it's a Scala feature. A parameter might be within parentheses or within curly braces. The latter enables the parameter to be a block of code.

    In this case, we defined an HTML block that refers another template, listContainer, just as any other function. That's how templates are combined in Play! 2.

So far so good? Well, not exactly. Looking closely at the listContainer call in the index.scala.html template, we'll see that it still needs some parameters.

Let's see how to fill them.

Passing data structures

Having composed our templates (index.scala.html using listContainer), we need to do two more things:

  • Adapt the parameter list of index.scala.html using curried parameters (two sets of one parameter in this case)
  • Adapt the index action in the Application controller to match the new needs

First we will modify the template to allow access to data usable by listContainer:

Passing data structures

For that, we added a new parameter block that adds the required data. A new parameter block is not mandatory; it's just a good way to have a clear distinction of what is needed by what. Then the data is simply re-used within the listContainer call.

If we try to hit the index.scala.html page right now, we'll see the same error screen as the following screenshot:

Passing data structures

This happens when we use our Java project and we notice that the template compilation failed because parameters are missing in the template call from within the Application.java#index action.

Note

Currying is not allowed in Java; but our template function is. However, it is not a big deal. Indeed, some magic happens in order to adapt our Scala function by taking two blocks of parameters into a Java render method, which takes all parameters collapsed in a single parameter block.

So, let's go to this action to pass it an integer value and a collection of strings:

Passing data structures

Now let's check again in the browser:

Passing data structures

Ouch! Interestingly, in the Scala template we used a Scala collection to represent our data; but going back to the controller (Java in this case), we're unable to use the classic java.util.List collection to create our server-side data.

In order to solve this problem, there are some conversion utilities available in Scala, which can be found in scala.collection.JavaConversions. This class provides a static method that will help us in converting our Java List to a Scala Seq: asScalaBuffer.

Passing data structures

Normally, everything should be OK now and we should get the following screenshot:

Passing data structures

Note

Actually, since this was only an example we could have used java.util.List directly in the template. But as the Play! 2 project could involve Java or Scala code, it's better to use a dedicated language for the templates.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset