Julien Richard-Foy’s blog

Composite user interface without boilerplate using Play 2

In Web applications, page content often follows a layout composed of several parts. For example a header showing the application’s name and user’s profile or account information, a main content area and a footer containing copyright materials. In some cases, such fragments are static (e.g. footers): they do not depend on the user viewing the page. In some other cases, though, these fragments are dynamic and require to be passed data to render (e.g. user profile information).

With a framework like Play 2, where templates are statically typed, that means that for each page having a layout containing such a dynamic fragment you have to compute the fragment’s required data and pass it to the template rendering function. In a sense, that is a good thing because if you try to render a template requiring data you’ve not provided, your application will not even compile. You’re guaranteed that, if your application compiles, you won’t have bad surprises like a “ReferenceError: foo is not defined” runtime exception when your clients will use the application. But, on the other hand, that is boilerplate to be required, for each page, to explicitly compute the data and pass it to the template rendering function. Thankfully, Play 2 allows you to write such things without boilerplate.

We’ll write a simple use case application and show how to get rid of the boilerplate. The application contains several pages sharing a same layout that contains a header part showing the current user status (i.e. logged in or not):

screenshot1 screenshot2

A first iteration could lead to the following (boilerplate) code:

The Application controller defines two actions, corresponding to the two pages of the application: index and show. These two actions render a template and pass it user(session) as first parameter. This function (defined just below the two actions) retrieves the current user from the session. As we can see, following this pattern, if we had ten actions we would have to write ten times the code retrieving the current user and passing it to the template rendering function.

Now let’s look at the show template (the index template is similar):

The code is pretty simple: it just calls a main layout function and writes the message argument as the page content. As you can see, we have to explicitly carry the user parameter up to the main layout rendering template.

Now that the problem is clear, how can we solve it?

Since we don’t want to have to write the user parameter, we can declare it as an implicit parameter in the templates:

By declaring it as an implicit parameter in all templates (including the main template) we are not anymore required to pass it explicitly through the templates hierarchy. In our case, we only had one parameter, so can write @main { … instead of @main(user) { …, but if we’ve had several parameters it would have saved a lot of characters!

Now that the boilerplate is reduced in the templates, let’s reduce it in the controllers. We have to find a way to provide an implicit value of type Option[User] in each action. We can do that by simply declaring the user method and its parameter as implicit:

Since Play’s controllers define an implicit value of type Session, our user method will be implicitly called by the Scala compiler each time an implicit value of type Option[User] is required (and not explicitly supplied). This implicit method allows us to skip the user template parameter, as shown above.

As a last refinement, let’s see how we can turn the behavior of being able to provide a user into a more reusable feature able to be mixed it into any other controller. That’s actually pretty straightforward: we just need to put the user method in a separate trait, say Users, and then mix this trait into any controller to make it able to deal with users:

A runnable Play 2 application based on this post is available on my GitHub page.

blog comments powered by Disqus