El sistema de plantillas por defecto de play está basado en Groovy. La versión de play de Scala, viene con un sistema de plantilla basado en Scala. La ventaja de este sistema de plantilla es que Scala es un lenguaje de tipado estático, por lo tanto si hay error de tipo los dará en tiempo de compilación y no en tiempo de compilación. Para la versión 2.0 de Play tienen planeado sustituir el motor de plantillas de Groovy por el de Scala.

Los elementos básicos del sistema de plantilla son:

Nuestra primera plantilla

Ya teníamos creado nuestro primero controlador, ahora nos hace falta la primera plantilla para poder ver los resultados. Lo que haremos es listar la lista de tweets.

Creamos el fichero con apps/views/Timeline/index.html

Cuando se utiliza el método render, por defecto play busca una plantilla en la carpeta apps/views/{Controlador}/{action}. Si quieres especificar otro nombre a la plantilla puedes utilizar el método renderTemplate("plantilla", parametros...)

1
2
3
4
#{extends ‘main.html’ /}

{set title:‘Timeline’ /}

${tweets}

Con el extends estamos diciendo que plantilla queremos utilizar. El set nos permite fijar variables que se van a utilizar dentro de la plantilla. Con ${tweets} estamos mostrando los tweets, que fueron pasados como parámetros del render.

Abrimos el navegados http://localhost:9000/

Y deberíamos ver algo tipo:

[]

Esta es la representación que hace Groovy de una lista vacía. Nuestra lista de tweets está vacia, así que vamos a llenarla con algunos datos de pruebas.

Poblando la base de datos al arranque de la aplicación

Como vamos a utilizar una base de datos en memoria, nos interesa que cada vez que arranque la aplicación se llene con algunos datos de prueba. Para ellos vamos a utilizar los Jobs de Play.

Creamos una nueva clase en app/app/Bootstrap.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package app;

import models.User; import play.jobs.Job; import play.jobs.OnApplicationStart; import play.test.Fixtures;

@OnApplicationStart public class Bootstrap extends Job {

<span class="kd">public</span> <span class="kt">void</span> <span class="nf">doJob</span><span class="o">(){</span>
    <span class="k">if</span><span class="o">(</span><span class="n">User</span><span class="o">.</span><span class="na">count</span><span class="o">()</span> <span class="o">==</span> <span class="mi">0</span><span class="o">){</span>
        <span class="n">Fixtures</span><span class="o">.</span><span class="na">loadModels</span><span class="o">(</span><span class="s">"initial-data.yml"</span><span class="o">);</span>
    <span class="o">}</span>
<span class="o">}</span>

}

Con la anotación @OnApplicationStart le estamos diciendo a Play que queremos que nuestro Job se ejecute cada vez que arranque la aplicación. Los Job deben extender de la clase play.jobs.Job e implementar el método doJob que es el método que se invocará. En el método estamos utilizando la clase Fixtures que ya conocemos para cargar datos en base de datos a partir de un fichero yml.

Además de la anotación @OnApplicationStart existen otras anotaciones para programar Jobs:

Si actualizamos la página http://localhost:9000/ deberíamos ver algo parecido a:

[Tweet[9], Tweet[8], Tweet[7], Tweet[6], Tweet[5], Tweet[4], Tweet[3], Tweet[2], Tweet[1]]

Utilizando scripts dentro de las vistas

Hasta ahora lo que estábamos mostrando es el .toString() de los objetos, que por defecto muestra NombreClase[id]. Vamos a cambiar nuestra vista para que muestra la información de cada uno de los tweets.

Dentro de los bloques de %{}% podemos utilizar código groovy. Por ejemplo, un bucle for para recorrer todos los tweets.

1
2
3
4
5
6
7
8
9
10
11
12
13
#{extends ‘main.html’ /}

{set title:‘Timeline’ /}

%{ for(tweet in tweets){ }% <div class=“tweet”> <div class=“tweet-author”>${tweet.author.username}</div> <div class=“tweet-msg”>${tweet.msg}</div> <div class=“tweet-date”>${tweet.date}</div> </div> %{ } %}

Utilizando tags

Los bloques de scripts están bien, pero a veces puede quedar la sintaxis un poco engorrosa. Para solucionar esto están los #{tags /}. Play viene con una serie de tags por defecto.

En este caso nos vendría bien utilizar el tag #{list /}

1
2
3
4
5
6
7
8
9
10
#{extends ‘main.html’ /}

{set title:‘Timeline’ /}

{list items:tweets, as:‘tweet’}

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"tweet"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"tweet-author"</span><span class="nt">&gt;</span>${tweet.author.username}<span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"tweet-msg"</span><span class="nt">&gt;</span>${tweet.msg}<span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"tweet-date"</span><span class="nt">&gt;</span>${tweet.date}<span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>

{/list}

Creando nuestros propios tags

Puedes definirte tus propios tags y escribirlos en Groovy o directamente en Java. Es una buena práctica crear tags para elementos que repitas en varias páginas, así el código no se duplica, sino se sustituye por llamadas al tag.

En este caso, parece que la forma de representar un tweet puede repetirse en varias páginas, por ejemplo el timeline, la lista de mensajes privados y así. Vamos a crear un tag para no tener que repetir el código.

Los tags se crean en la carpeta app/view/tags. El nombre del fichero, será el nombre del tag. Los tags pueden recibir parámetro. Dentro del tag estarán disponibles con $nombreParametro. El parámetro por defecto es $arg.

app/views/tags/renderTweet.html

1
2
3
4
5
<div class=“tweet”>
    <div class=“tweet-author”>${arg.author.username}</div>
    <div class=“tweet-msg”>${arg.msg}</div>
    <div class=“tweet-date”>${_arg.date}</div>
</div>

Cambiamos nuestra vista para hacer la llamada al tag

app/view/Timeline/index.html

1
2
3
4
5
6
#{extends ‘main.html’ /}

{set title:‘Timeline’ /}

{list items:tweets, as:‘tweet’}

#{renderTweet tweet /}

{/list}

Ejercicio: Tag para mostrar gráfica

Como ejercicio vamos a crear un tag que permita mostrar una graáfica.

Pasos:

1
2
3
4
5
6
7
8
  #{grafica items:user_tweets,
              title:‘Tweets de usuarios’,
              xTitle:‘Usuario’,
              yTitle:‘Tweets’,
              id:‘user_tweet’,
              width:500,
              height:400
    /}

Consejos:

Solución

Crea la nueva ruta

conf/routes

1
GET     /stats                                    Timeline.stats

Crea el nuevo método del controlador

app/controllers/Timeline.java

1
2
3
4
public static void stats(){
    List<Object[]> user_tweets = JPA.em().createQuery(“select t.author.username, count(t) from Tweet t group by t.author”).getResultList();
    render(user_tweets);
}

Crea el tag, utilizando la documentación de Google Chart y haciendo la sustitución de variables en los lugares adecuados.

apps/views/tags/grafica.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<script src=“https://www.google.com/jsapi”></script>
<script>
      google.load(“visualization”, “1”, {packages:[“corechart”]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn(‘string’, ‘${xTitle}’);
        data.addColumn(‘number’, ‘${yTitle}’);

    <span class="nx">data</span><span class="p">.</span><span class="nx">addRows</span><span class="p">(</span><span class="nx">$</span><span class="p">{</span><span class="nx">_items</span><span class="p">.</span><span class="nx">size</span><span class="p">()});</span>
    <span class="err">#</span><span class="p">{</span><span class="nx">list</span> <span class="nx">items</span><span class="err">:</span><span class="nx">_items</span><span class="p">,</span> <span class="nx">as</span><span class="err">:</span><span class="s1">'item'</span><span class="p">}</span>
        <span class="nx">data</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="nx">$</span><span class="p">{</span><span class="nx">item_index</span> <span class="o">-</span><span class="mi">1</span><span class="p">},</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'${item[0]}'</span><span class="p">);</span>
        <span class="nx">data</span><span class="p">.</span><span class="nx">setValue</span><span class="p">(</span><span class="nx">$</span><span class="p">{</span><span class="nx">item_index</span> <span class="o">-</span><span class="mi">1</span><span class="p">},</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">$</span><span class="p">{</span><span class="nx">item</span><span class="p">[</span><span class="mi">1</span><span class="p">]});</span>        
    <span class="err">#</span><span class="p">{</span><span class="sr">/list</span><span class="err">}


var chart = new google.visualization.ColumnChart(document.getElementById(‘${id}’)); chart.draw(data, {width: ${width}, height: ${height}, title: ‘${title}’}); } </script> <div id=“${_id}”></div>

Crea la vista donde se llame al tag

apps/views/Timeline/stats.js

1
2
3
4
5
6
7
8
9
10
11
 #{extends ‘main.html’ /}
    #{set title:‘Estadísticas’ /}

#{grafica items:user_tweets, 
          title:'Tweets de usuarios', 
          xTitle:'Usuario', 
          yTitle:'Tweets', 
          id:'user_tweet', 
          width:500, 
          height:400 
/}<span class="w">