Play – Exécuter un template depuis un Controller (render, renderTemplate, …)

Dans le tutorial précédent, on a vu qu’un Controller Play peut renvoyer différents type de données grâce notamment à des méthodes spécialisées comme renderJSON ou renderBinary:

Play – Controller et les variantes de render() (JSON, XML, fichier, …)

Vous allez aussi utiliser les Controller Play pour servir les pages HTML de votre site web. En effet, c’est Play votre serveur web (enfin Netty), qui devra répondre du contenu HTML lorsque vous l’interrogez sur une certaine URL (une « route »).

Dans cet article, on va utiliser la notion de « Template » dans Play. Un Template est un fichier à l’extension « .html », qui va contenir un mélange de HTML (+JavaScript éventuellement) et du Groovy (un peu comme Java) qui vous permet de réaliser des actions sur ce Template (boucles, conditions, …). Voici un petit exemple de Template:

<h1>Client ${client.name}</h1>
<ul>
    #{list items:client.accounts, as:'account' }
        <li>${account}</li>
    #{/list}
</ul>

Ce template devra être « interprété » pour au final cracher du HTML. C’est une étape que l’on appelle « exécution » d’un template. Celle-ci va être réalisée par vos Controller.

Notez que vous pouvez aussi utiliser les templates pour rendre autre chose que du HTML, du JSON par exemple. Un template permet de faciliter la génération de contenu complexe.

Conventions de nommage pour la liaison Controller / Template

Admettons que vous ayez l’instruction suivante:

public class Clients extends Controller {

    public static void index() {
        render();
    }
}

Votre Controller se trouve donc à l’emplacement /app/controllers/Clients.java. Lorsque vous allez appeler la méthode render(), Play va automatiquement aller cherche un Template à l’emplacement:

app/views/Clients/index.html

On verra plus loin que l’on peut bien sûr changer ce comportement par défaut et appeler un autre template.

Faire passer de la donnée du Controller vers le Template

Dans l’exemple plus haut, on a simplement appelé la méthode « render() ». Le template sera donc exécuté sans aucune donnée en entrée. Ce que l’on va plutôt chercher à faire, c’est passer des données au template (une liste de Clients par exemple) et laisse le template faire le rendu de cette liste de clients. Pour cela, vous avez deux méthodes.

La méthode simple qui consiste à passer les données en paramètre de la méthode render():

public static void show(Long id) {
    Client client = Client.findById(id);
    render(client);
}

Ou alors, vous pouvez passer par la map « renderArgs » pour passer des arguments de manière arbitraire:

public class Clients extends Controller {

    public static void show(Long id) {
        Client client = Client.findById(id);
        renderArgs.put("client", client);
        render();
    }
}

Ces deux morceaux de code sont strictement équivalents.

De cette manière, la variable « client » sera définie lors de l’exécution du template. Avec la notation suivante, on peut aller chercher un attribut de notre objet Client:

<h1>Client ${client.name}</h1>

Spécifier un Template différent du Template par défaut

Pour spécifier un autre Template que celui par défaut défini pas les conventions de nommage Play, utiliser la méthode renderTemplate(…) en passant le chemin du template en premier paramètre:

public static void show(Long id) {
    Client client = Client.findById(id);
    renderTemplate("Clients/showClient.html", id, client);
}

Redirection vers une URL

La méthode redirect(…) vous permet de rediriger l’utilisateur vers une page de votre choix, en donnant les bons headers HTTP (302 je crois):

public static void index() {
    redirect("http://www.zenexity.fr");
}

Redirection « interne » au sein d’un Controller

Une instruction render n’est pas une instruction return. A la fin de la méthode de votre Controller, vous pouvez donc appeler une autre action, qui elle, va appeler render().

Prenons ce Controller:

public class Clients extends Controller {

    public static void show(Long id) {
        Client client = Client.findById(id);
        render(client);
    }

    public static void create(String name) {
        Client client = new Client(name);
        client.save();
        show(client.id);
    }
}

Et les routes suivantes dans votre fichier de configuration:

GET    /clients/{id}            Clients.show
POST   /clients                 Clients.create

Voici le chemin que va prendre une requête POST sur l’URI /clients:

  • Envoi de la requête POST par le navigateur
  • Le Router invoke la méthode « create » du Controller Clients
  • La méthode « create » appelle la méthode « show » directement
  • L’appel est intercepté par Play qui va faire un routing inverse (méthode Java > Route) et créer l’URL nécessaire à l’appel de la méthode « show » ayant le paramètre id
  • La réponse HTTP reçue par le browser sera un 302 Location:/clients/3132 (où 3132 est l’id du Client créé dans create)
  • Le browser effectue un GET /clients/3132, qui va passer par le Router et effectuer un render(client).

Une réflexion au sujet de « Play – Exécuter un template depuis un Controller (render, renderTemplate, …) »

  1. Benoît

    Salut,

    J’aime beaucoup tes sites de tutos, pratiques et facilement utilisables.

    Juste une remarque (sûrement une erreur d’inattention).
    Dans ton paragrapahe « Spécifier un Template différent du Template par défaut« , tu écris «  utiliser la méthode renderTemplate(…) en passant le chemin du template en second paramètre« .
    Pourtant dans ta ligne de code, il est en premier paramètre :
    renderTemplate("Clients/showClient.html", id, client);

    Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *