Playing around

Now that we have a good understanding of how a template can help in creating views, we'll try to adapt our templates to make them interesting. The idea is to fix all the concepts seen so far in your mind.

Laying out

In the first section, we created a listContainer template that was able to render a sequence of strings into a ul HTML element. In this section, we'll adapt it a bit to enable a header and a footer around the list. For that, we'll use currying and the internal HTML representation of Play! 2.

So, all we have to do is redefine the listContainer function to take two new parameter blocks, header and footer, which are HTML excerpts.

Laying out

As expected, the type of these new parameters is Html, which is the internal representation of HTML blocks in Play! 2. Then, we use them right before and right after the block disPlay!ing the list, and we remove the previoush1 element (which was saying Here we go!).

Note

We also encapsulated the whole thing into a dedicated div element, which is holding the style attribute to shift everything at once.

OK, now we must change the calling instruction in the index.scala.html template by adding the header and footer HTML, shown as follows:

Laying out

That simple! We just created the "classic" header-body-footer layout, where the former and the latter are simply passed as parameters. Having a look at their type, Html, and how we passed them, we can see that we just wrote an HTML block (including the Scala one) at will.

The following screenshot shows the result in the browser:

Laying out

Using domain models

Up until now, we played with integers and character strings; that was really cool, but not so representative of what we will face in the real world. Most of the time we're dealing with domain model instances that may represent complex object trees and myriad properties.

In this section, we will create an Item class that will be used in place of String in the list of things to be disPlay!ed. The following screenshot shows this (in both Scala and Java):

Using domain models

As you can see from the previous screenshot, we created the class in the models package; this is because we've just introduced the last component of our MVC pattern (the M part). As a Controller is defined in the controllers package and a View in the views package, a Model commonly resides in the models package.

Note

The same remark applies for the models package as did for the views one. It's no longer mandatory, but it's a rule of thumb to place models under the models package. For instance, the models package is imported by default in templates.

To use it, we must perform the following steps:

  1. Change the list parameter in the listContainer and index templates to use the new Item class rather than String.
  2. Adapt the index action to create items and not strings.

What would have to be done is to modify the rendering of the list to use the data of Item. However, we'll take this opportunity to create a dedicated template: listItem.scala.html.

This template is meant to render an item within a list (ul), which could be achieved in the following way:

Using domain models

Note

We added a quick and dirty styling instruction, but we'll see in the coming sections that LESS could be used instead. Furthermore, this tag being here means that it will be added for every single item, which is not desirable obviously.

Now that we've seen a lot of templates, listItem.scala.html should look familiar. The only thing that is very new is the @import statement, which should be self-explanatory.

Let's use it in the listContainer template:

Using domain models

We simply adapted the list by renaming it items, changing its type from Seq[String] to Seq[Item], and finally calling the listItem template in the map body.

Note

Reflecting the same changes in the index template will be left as an exercise. However, one could just check the source code provided in the code files of the book.

The last thing that is needed is to modify the action to create an Item sequence. The following screenshot shows the Scala version (the Java one is left as an exercise):

Using domain models

Having done all of the adaptation, we can return to our browser and check what's going on.

Using domain models

Cool, huh? But we could do better, couldn't we?

Note

The quote shown in the previous screenshot has been extracted from probably one of the greatest movies ever—Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb.

Re-using our code

In this section, we'll enjoy ourselves a bit by playing with what we have seen and learned so far, in order to make our application look more interesting.

The following screenshot shows what the goal is:

Re-using our code

At this stage, we're able to show a list of items with a header and a footer, which together would define a new structure: Chat. A chat is a discussion between people and can occur several times in a single day. So, the following screenshot shows the definition of this class:

Re-using our code

Quite simple and obvious. But now we're going to try to use it as the top-level type of our application; thus the index page should render Chat instances rather than Item.

For that, we'll have to change the signature of the index template to only take a list of Chat instances (note that we'll use java.util.List for convenience in the Java controller). Then we'll have to adapt the listContainer template to take a single Chat instance; so we will have totally removed the level parameter from the scope.

Re-using our code

The previous screenshot shows a very simple code example that creates a bunch of Chat instances with underlying items.

For such use cases, that is, initializing with test data, Play! has a special feature that enables a much higher level of control over the application. This feature is called a global object. Such an object is a singleton that will be created by Play! at startup and will provide plenty of hooks such as onStart and onBadRequest. This object in Scala or class in Java should be created keeping in mind the following points:

  • It must extend the GlobalSettings type (provide default implementations for all hooks)
  • It must either be declared at the root of the application with the name Global, or its fully qualified path must be configured in the application.conf file using the key application.global

With this object created, one could override onStart in such a way that data can be created for testing purposes.

Note

Application-wide hooks take an Application instance as parameter, which allows us to execute code whether we are in the Dev or Prod mode. Because mode is a field of the Application controller, it can have one of the following values: Dev, Prod, or Test.

The problem now is that the Chat instances are completely shuffled, and if we leave the listContainer template as is, we'll get something similar to the following screenshot:

Re-using our code

Which is ugly!

To solve this, we'll use Scala at full power by using the following methods: sortBy and groupBy on Seq, and toSeq on Map. The following screenshot shows our new "empowered" template:

Re-using our code

Note

As we can see from the previous screenshot, we're able to use the methods we saw in Chapter 2, Scala – Taking the First Step, on java.util.List. That's because of some magic that implicitly converts List instances to Seq on the fly. But we won't cover this in the book.

Calling this template, we get a not found: dataAndChats error. This is because of the formatting used to align the methods chaining after @chats. This is a sad limitation of the template compiler, it needs Scala stuff to be single lined if not wrapped in curly braces.

In short, the following steps explain what has been done on the chats list:

  1. We sorted all instances based on their occurrence.
  2. We grouped instances that have a similar date, resulting in a Map instance where the date is the key and the list of chats is the value.
  3. We converted the resulting map's items into a sequence of tuples (key-value pairs).
  4. We sorted this sequence by the first element of the tuples (the date).
  5. Finally, we mapped all tuple instances to an HTML excerpt.

Note

A Tuple2 class in Scala has two properties, _1 and _2; these can be seen as key and value when they represent a key-value pair.

Checking back in the browser, we'll get the result disPlay!ed at the start of this section.

Funny, huh? Now, try to make exactly the same kind of sorting and grouping using Java; (just joking).

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

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