1

We have been having discussions in our product dev team regarding html maintainability and reuse. To set the context, we started with HTML5/CSS3 front end with plain JS under Play MVC, which in turn uses RESTful backend. Then we thought of adding AngularJS to the spin and to adopting a hybrid approach only to realize that two strong MVC frameworks don't necessarily work together and you have to pick one. So for the performance and type-safety among other issues, we decided to go with using Play framework and Scala based templates.

Here's the challenge: We would like to create reusable web components just like Apache Tiles, so that common elements such as header, menus, footer, etc. can be reused. These components are ready to go in Play to which dynamic content could be added to serve the entire page.

Can this be done? If yes, how?

Secondly, play templates seem to take you back in the time since they don't allow the separation of concern in html. Therefore for re-designing or improving html content, the html developer will have to deal with the template or merging new html with existing templates. How to make this process easier?

Michael Zajac
  • 55,144
  • 7
  • 113
  • 138

2 Answers2

5

I'm don't know exactly how Apache Tiles works, but if I properly understand, it offers a way to create pages using smaller components (like header, menu, footer, etc) and some sort of include mechanism to glue these components together and then compose the page.

That said, you can achieve the same thing using Twirl. You just need to declare reusable blocks that can be used inside the same page, or you can have something like Rails partials that can be reused across different pages.

Let's see an example. Consider that you have the following files:

File app/views/partials/header.scala.html:

<header>
  <h1>My Header</h1>
</header>

File app/views/partials/navigation.scala.html:

<nav>
  <ul>
    <li><a href="/home">Home</a></li>
    <li><a href="/profile">Profile</a></li>
    <li><a href="/faq">FAQ</a></li>
  </ul>
</nav>

File app/views/partials/footer.scala.html:

<footer>
  Some copyright info
</footer>

File app/views/main.scala.html:

@(title: String)(content: Html)

<!DOCTYPE html>

<html lang="en">
    <head>
        <title>@title</title>
        <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")">
        <script src="@routes.Assets.versioned("javascripts/hello.js")" type="text/javascript"></script>
    </head>
    <body>
        @partials.header()
        @partials.navigation()

        @content

        @partials.footer()
    </body>
</html>

The files above defines not only some reusable partial templates (header, navigation and footer), but also a common layout (main) that all the pages of your application can reuse. Now, lets see a page that uses the structure above:

File app/views/users/profile.scala.html:

@(user: models.User)

@main(title = "User Profile Page") {
  <h2>This is the profile page of @user.username</h2>
}

And there is more: since views are compiled to Scala code, you can import code written in Scala/Java and call it directly from your views, something like Rails view helpers:

File app/views/helpers/DateHelpers.scala:

package views.helpers

object DateHelpers {

  def formatToISO8601(date: Date) = {
    ??? // format the date
  }

}

Let's use this helper in our app/views/users/profile.scala.html page:

@(user: models.User)
@import controllers.DateHelpers._

@main(title = "User Profile Page") {
  <h2>This is the profile page of @user.username.</h2>

  <p>User since @formatToISO8601(user.createdAt)</p>
}

And there are other approaches to consider:

  1. Ping-Play: Big Pipe Streaming for the Play Framework
  2. You can create a Play module that integrate with Apache Tiles. I'm pretty sure this is possible.
marcospereira
  • 12,045
  • 3
  • 46
  • 52
0

A quick answer would be the following. If you are comfortable with Yeoman, you can keep most of the UI part in existing HTML, while rendering some pages with Scala templates. I would recommend Play-yeoman, which may help such that you can--with minimum effort--reuse UI components.

For instance, you may easily convert a NodeJS+Angular app into Play+Angular. The Play-yeoman plugin helps a lot. But it is not so flexible as it does not support any arbitrary Yeoman configuration, just Angular.

mcku
  • 1,351
  • 12
  • 23