Les pages d'une application Web possèdent souvent sur la même structure. Afin d'éviter la redondance de code et de s'assurer de l'uniformité visuel, un système de templating est nécessaire. Nous avons tous utilisé soit sitemesh soit tiles afin de répondre à ce besoin. Les deux technologies nécessitent une configuration XML afin de décrire l'assemblage des pages. En Wicket la gestion de la structure des pages est beaucoup plus simple ! Cela se fait soit par héritage soit par composition.
Nous allons focaliser dans ce billet sur l'héritage et modifier la page d'accueil en conséquence.
Nous allons commencer par créer une classe abstraite, TemplatePage.java, dont vont hériter les pages de notre application de gestion de contact.
public abstract class TemplatePage extends WebPage { }
Cette classe ne possède pour le moment aucun composants commun aux pages de l'application, par contre souvenons nous que chaque classe Java représentant une page possède un markup html associé. Nous allons donc créer le fichier TemplatePage.html qui contiendra la structure générale des pages de notre application.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org" xml:lang="fr"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <meta name="author" content="Zenika" /> <link href="css/zencontact.css" media="screen" rel="stylesheet" type="text/css" /> </head> <body> <div id="header"> <a href="WelcomePage.html">Accueil</a> | <a href="ListContactPage.html">Liste des contacts</a> | <a href="EditContactPage.html">Créer un contact</a> </div> <div id="content"> <div id="contacts"> <div class="contact"> <wicket:child/> </div> </div> </div> <div id="footer"> <p id="legal"><a href="http://www.zenika.com/">Zenika</a> Copyright© 2009</p> </div> </body> </html>
On remarque les 3 zones, représentées par des div que sont :
- La zone d'identifiant « header », partie contenant le menu
- La zone d'identifiant « content », partie contenant les éléments spécifiques à chaque page
- La zone d'identifiant « footer », partie contenant la mention de copyright
Nous remarquons aussi, à la ligne 28, la balise <wicket:child/> qui représente l'endroit ou le code HTML des sous classes va être inséré.
Maintenant, modifions la classe Java de la page d'accueil afin de ne plus la faire hériter directement de la classe WebPage de Wicket, mais de la classe TemplatePage que nous venons de créer.
public class WelcomePage extends TemplatePage { … }
Il reste maintenant à modifier le template html de cette page afin de retirer toutes les parties inutiles et ne conserver que le spécifique à la page d'accueil.
<?xml version="1.0" encoding="UTF-8"?> <wicket:extend> <table> <tr> <td width="300px"><img src="images/zenika_logo.png"/></td> <td width="300px"><img src="images/pjug_logo.png"/></td> </tr> </table> <br/><br/><br/> <div wicket:id="date">[24 fŽvrier 2009]</div> </wicket:extend>
On parle de Markup Inheritance car Wicket, lors du rendu de la page d'accueil, fera correspondre l'héritage Java des pages en fusionnant les templates HTML correspondant. Ainsi le contenu HTML de la balise <wicket:extend> de la page WelcomePage viendra enrichir le code HTML au niveau de la balise <wicket:child/> de la page TemplatePage.
Il ne reste plus qu'a redémarrer le serveur et tester l'affichage de la page depuis l'URL :
http://localhost:8080/zencontact
Si la page d'accueil s'affiche correctement, passons à l'étape suivante qui consiste à intégrer les deux dernières pages de la maquette.
Les classes Java correspondantes :
public class ListContactPage extends TemplatePage { }
public class EditContactPage extends TemplatePage { }
Les fichiers HTML correspondants :
ListContactPage.html
<wicket:extend> <table cellspacing="5" cellpadding="5"> <tr> <td><div><img src="images/people.png"/></div></td> <td><span>[Martjin]</span> <span>[Dashorst]</span></td> <td><a href="#"><img src="images/edit.png"/></a></td> </tr> <tr> <td><div><img src="images/people.png"/></div></td> <td><span>[Eelco]</span> <span>[Hillenius]</span></td> <td><a href="#"><img src="images/edit.png"/></a></td> </tr> </table> </wicket:extend>
EditContactPage.html
<wicket:extend> <form> <table cellspacing="5"> <tr> <td>Prénom :</td> <td><input class="type="text" /></td> </tr> <tr> <td>Nom : </td> <td><input type="text" /></td> </tr> <tr> <td>Date de naissance : </td> <td><input type="text" /></td> </tr> <tr> <td>Email : </td> <td><input type="text" /></td> </tr> <tr> <td><input type="reset" value="Annuler" class="button" /></td> <td><input type="submit" value="Valider" class="button" /></td> </tr> </table> <div id="errorsDiv" class="innerError"/> </form> </wicket:extend>
La navigation vers et entre ces pages n'est pas encore activée, ce sera l'objet du prochain billet.
Précédent : ZenContact 2 : Ajouter un libellé dynamiquement
Suivant ; ZenContact 4 : La navigation entre pages


Commentaires
Question : wicket ne permet qu'un seul wicket:child. Du coup, comment feriez-vous pour traiter le use case où une page aurait 2 zones templatées ? Par exemple une zone centrale et une zone sitebar optionnelle, avec une liste des articles du blog.
Je n'ai pas trovué de réponses élégantes et votre exemple prend le cas où une seule partie du template HTML principal est dérivé dans une classe fille. Merci
Bonjour Nicolas,
Avec Wicket il y'a deux façons objet, d'utiliser des templates. La composition et l'héritage.
Par héritage, nous retrouvons le mécanisme de <wicket:child/> qui est calquée sur l'héritage simple Java.
La composition, ce traduit en Wicket par l'utilisation de Panel. Les classes WebPage et Panel sont les deux classes principales associées à du markup HTML. Ainsi quand tu ajoutes un Panel à ta page, comme pour une sidebar par exemple, celui-ci vient avec son HTML / CSS etc....
Un autre moyen consisterait à avoir une hiérarchie de pages comme nous pourrions avoir une hiérarchie de classes et sous-classes.
En espérant avoir répondu à la question.
Tu peux par exemple avoir une page template de base BasePage sans barre latérale, dont hérite une page SideBarBasePage possédant la barre latérale. Les "vraies" pages de ton application peuvent alors hériter de l'une ou l'autre, en fonction du besoin.
L'autre approche est d'utiliser des Panels pour composer la page.
Bien sûr il est possible de combiner les deux techniques pour obtenir une flexibilité maximale.