Blue Flower

Chercher

Templates

1.  Définition

JSF  dispose d'une fonctionnalité   appelée  Templating qui permet de créer une page XHTML  servant comme base ou modèle aux  autres pages; cette page XHTML appelée template (gabarit) permet d'avoir des pages ayant la même structure. Le Templating facilite le  maintien d'un aspect standard pour un grand nombre de pages au sein d'une application web développée avec JSF.
Pour réaliser une page template on utilise un ensemble de tags issus du namespace   http://xmlns.jcp.org/jsf/facelets; ces tags sont préfixés par "ui" comme on le présentera dans la suite de cet article.

2. Les tags de Facelets spécifiques pour les templates

  Tags                                                                           Fonctions
ui:component
ce tag permet de définir un composant créé et ajouté à l'arbre des composants.
ui:composition Définit une composition de page (attribut template  optionnel); ce qui est à l’extérieur de ce tag est ignoré
ui:debug Définit un composant de debug qui est est créé et ajouté à l'arbre des composants.
ui:decorate   Similaire au tag composition mais n'ignore pas le contenu en dehors de ce tag.
ui:define   Définit un contenu qui est inséré dans une page par une template 
ui:fragment   Similaire au tag component mais n'ignore pas le contenu en dehors de ce tag
ui:include     Encapsule une autre page.
ui:insert   Insérer un contenu dans un template. Ce qu’il y a à l’intérieur de ce tag est le contenu par défaut
ui:param   Utilisé pour passer un paramètre dans un fichier passé par un "include".
ui:repeat utilisé comme une alternative pour les tags permettant de faire des boucles comme  c:forEach ou h:dataTable.
ui:remove Enlever un contenu d'une page

.....

On se sert de ces tags et d'autres tags "HTML" pour construire la page template (modèle ou Gabarit) qui permettra d'avoir une structure homogène de toutes les pages du projet où sera utilisé la template.  Comme page XHTML elle contient les espaces de noms relatives à XHTML, et comme Facelet on lui rajoute d'autres espaces de noms comme "xmlns:ui="http://xmlns.jcp.org/jsf/facelets"" et " xmlns:h="http://xmlns.jcp.org/jsf/html" ". Au sein de la template on s’intéressera spécialement aux tags "<ui:insert name ="nomDutag">" et  "</ui:insert>" qui délimitent les parties de la template qui seront remplacées par du contenu qui proviendra des templates clientes.

les différentes pages de  l'application qui utiliseront la page "template.xhtml" s'appellent des templates clientes; c'est au sein de ces celle-ci que seront définies les contenues des différents tags " <ui:insert ...". Dans la template cliente on aura par exemple des tags "<ui:define name="nomDutag">" et "</ui:define>" qui délimiteront ce qui sera inserré entre les tags "<ui:insert name ="nomDutag">" et  "</ui:insert>".
.....

Exemple de template  "template.xhtml"

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:h="http://xmlns.jcp.org/jsf/html">  
   <h:head>
       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      <h:outputStylesheet name="./css/default.css"/>
      <h:outputStylesheet name="./css/cssLayout.css"/>
      <title>#{pageTitle}</title>
      </h:head>
      <ui:param name="copyright" value="&copy; Aly Omara 2015"/>
  <h:body> 
 <div id="top">
  <ui:insert name="top">Top</ui:insert>
      </div>
       <div>
           <div id="left"> 
           <ui:insert name="left">Left</ui:insert>
           </div>
           <div id="content" class="left_content">
           <h1>#{pageTitle}</h1>
               <ui:insert name="content">Content</ui:insert>
           </div>
       </div>
      <div id="bottom">
      <ui:insert name="bottom">Template - #{copyright}</ui:insert>
      </div>  
     </h:body>
</html> 

Explications et détails:

( à suivre)...

Exemple de template cliente 

<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"  
template="./template.xhtml"              
    xmlns:h="http://xmlns.jcp.org/jsf/html"
    xmlns="http://www.w3.org/1999/xhtml">
 <ui:param name="pageTitle" value="Edit Person : #{bean.person.displayName}"/>
  <ui:define name="top">  
     Top of the page
    </ui:define>
    <ui:define name="content">
 <h:form>   
           <h:panelGrid columns="2">
      <h:outputLabel value="First Name" class="label"/> 
           <h:inputText value="#{bean.person.firstName}"/>   
              <h:outputLabel value="Last Name" class="label"/>
  <h:inputText value="#{bean.person.lastName}"/>
    <h:outputLabel value="Customer Notes" class="label"/>   
             <h:inputTextarea  value="#{bean.person.notes}"/>
 </h:panelGrid>
       </h:form>
    </ui:define>
   <ui:define name="bottom">
        Template Client Defined #{copyright}
     </ui:define>
</ui:composition>

3. Composants UI

Dans JSF on a deux grands types de composants UI; le premier type est l'ensemble de composants qui permettent d' initier une action comme cliquer sur un bouton par exemple,  et le deuxième type est l'ensemble de composants UI  qui fournissent des données comme "input" par exemple. Le comportement des différents composants JSF sont décrits et implémentés  soit par l'interface UICommand pour le premier type et par  l'un des deux interfaces ValueHilder ou EditableValueHolder  pour le  second type. L'interface EditableValueHolder permet aux composants d'avoir leurs valeurs modifiables par les utilisateurs. La raison d'être de ces interfaces est de fournir la plus haute abstraction possible permettant d'encapsuler les capacités des composants UIs (interface utilisateur) de JSF.
 ( à suivre)

4. Composants Composés

4.1. Définition

La technologie JavaServer Faces propose le concept de composants composés avec les Facelets et c'est ce qui permet à chacun de créer sa propre bibliothèques de tags; un composant composé est un nouveau composant créé à partir d'autres composants. Pour créer un composant composé, il faut créer un Facelet (fichier ".xhtml") qui contient la définition du composant composé; celle-ci est formée de deux parties :

  • Interface: c'est la partie qui décrit les attributs des balises associées au composant,
  • Implémentation, la partie du composant qui contient la définition des différents tags  du composant composé à créer.

Chaque composant peut avoir des validators, des convertors et des listeners qui lui sont attachés pour améliorer ses performances. Avec les Facelets toute page XHTML avec ses balises, ses tags JSF et ses composants peut être incluse dans une autre page ou utilisée comme élément d'un autre composant. On peut ainsi former des bibliothèques de composants pour des utilisations appropriées; toutefois avant de commencer à créer ses propres composants il faut vérifier s'il n'en existe pas déjà dans les différents tagLib associés à JSF.

4.2. Balises des Composants Composés

composite: interface
Cette balise déclare qu'on va utiliser un composant pour un composant composé. Le composant composé peut être utilisé comme simple composant.
composite: implementation
Cette balise définit l'implémentation du composant précisé dans la balise <composite:interface ...>.
composite:attribute
Cette balise déclare un attribut qui sera donné à une instance du composant composé au sein duquel il est présent. Pour de plus amples informations il faut voir la liste complète des tags dans la documentation des facelets.

composite: insertChildren
cette Balise est utilisée dans un marqueur <composite:implementation>. Tous les composants fils ou les templates seront insérés dans la représentation de ce composant.

composite: valueHolder
cette Balise précise que le composant composé qui lui est associé est déclaré par le marqueur "composite:interface" .... (à compléter)

composite: editableValueHolder
... (à faire)

composite: actionSource
...(à faire).

4.3. Interface et implémentation

Les tags  'composite: interface', 'composite: attribute' et 'composite: implementation'  de 'composite'  servent à définir le contenu de chaque 'composant composé'.

Interface

Le tag composite: interface  est utilisé pour déclarer les valeurs configurables qui sont exposées au développeur qui l'utilisent.

Implémentation

Le tag 'composite:implementation' déclare toutes les balises XHTML qui seront contenues dans le composant composé.

Exemples d'utilisation
  Considérons les lignes de codes suivantes qui seraient appelées à apparaître dans plusieurs page (Facelets) pour un formulaire qui permet de se connecter sur une page au sein d'une application:

 <h:form>
<h:panelGrid columns="3"> <h:outputText value="Name:" /> <h:inputText value="#{user.name}" id="name"/> <h:message for="name" style="color: red" /> <h:outputText value="Password:" /> <h:inputText value="#{user.password}" id="password"/> <h:message for="password" style="color: red" /> </h:panelGrid> <h:commandButton actionListener="#{userService.register}" id="loginButton" action="status" value="submit"/> </h:form>

Pour éviter de réécrire ces lignes on peut définir un composant composé comme suit:
1. on crée un fichier XHTML qu'on va appeler ici "login.xhtml" par exemple, on y inscrit le code ci-dessus et on sauvegarde ce fichier dans le répertoire "ressources/repertoire_des-composant_composite" (le répertoire est un répertoire classique de toute application JSF)
2. on crée un espace de nom (appelons ce espace de nom "mon_composite") et on l'ajoute aux différents espaces de nom de l'application
3. On complète la définition de notre composant composite en précisant les parties  "interface" et "implementation"  ce qui donne comme fichier "login.xhtml":

Exemple de fichier composant composé

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
xmlns:h="http://xmlns.jcp.org/jsf/html">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="name"/>
<cc:attribute name="password"/>
<cc:attribute name="actionListener"
method-signature=
"void action(javax.faces.event.Event)"
targets="ccForm:loginButton"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<h:form id="ccForm">
<h:panelGrid columns="3">
<h:outputText value="Name:" />
<h:inputText value="#{cc.attrs.name}" id="name"/>
<h:message for="name" style="color: red" />
<h:outputText value="Password:" />
<h:inputText value="#{cc.attrs.password}"
id="password"/>
<h:message for="password" style="color: red" />
</h:panelGrid>
<h:commandButton id="loginButton"
action="status"
value="submit"/>
</h:form>
</cc:implementation>
</html>

 ....

Dans ce fichier "login.xhtml" on a défini le composant composé qu'on va utiliser dans d'autre fichier (Facelet) qui nécessite un formulaire login. Mais comment faire?
L'espace de nom du composant composite sera une association de "http://xmlns.jcp.org/jsf/composite" et "repertoire_des-composant_composite". Le nom du nouveau tag ainsi créé est le  nom du fichier contenant la définition du composant composé sans l'extension ".xhtml" . si on définit l'espace de nom comme suit:
"xmlns:mc="http://xmlns.jcp.org/jsf/composite/repertoire_des-composant_composite"
Alors dans les facelets utilisant le composant composé on aura  le tag <mc:login  ....> comme présenté ci-dessous:

<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:mc="http://xmlns.jcp.org/jsf/composite/mycomp"
<!-- . . . -->
<mc:login/>
</html>

  ...

précédent suivant