Bon pour relecture
Sommaire :
Présentation
Facelet est une technologie JSF permettant de créer des templates (ou modèles) et d'utiliser ces templates dans les vues de l'application.
Le but est de factoriser les éléments communs à un ensemble de pages qu'on déclarera plutôt dans une page unique, appelée template. Les pages utilisent alors le template comme structure et y injectent leur contenu spécifique.
Intérêts :
- Eviter les duplications de code et faciliter son maintien
- Améliorer la visibilité des pages puisque chaque page ne présentera que ce qui lui est propre
- Avoir une structuration de page uniforme dans toute l'application
Fonctionnement
Déclaration
Dans JSF 1.2, on indique à JSF d'utiliser Facelets comme gestionnaire de vues. Pour cela, on ajoute dans /webapp/WEB-INF/jsp/faces-config.xml
<application> [...] <view-handler>com.sun.facelets.FaceletViewHandler</view-handler> [...] </application>
Inutile en JSF 2.0
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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:t="http://myfaces.apache.org/tomahawk"> <head> <title><ui:insert name="titre" /></title> </head> <body> <p> <ui:insert name="contenu" /> </p> </body> </html>
Les balises <ui:insert> indiquent les endroits où le code spécifique pourra être injecté.
Exemple de page utilisant le template : ma_page.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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <ui:composition template="/template.xhtml"> <ui:define name="titre">Titre de ma page</ui:define> <ui:define name="contenu"> Texte, formulaires etc. </ui:define> </ui:composition> </html>
La balise <ui:composition> indique le template qui va être utilisé.
Les balises <ui:define> permettent de définir les contenus spécifiques à la page (élément identifié via l'attribut name).
Résultat obtenu :
<!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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:t="http://myfaces.apache.org/tomahawk"> <head> <title>Titre de ma page</title> </head> <body> <p> Texte, formulaires etc. </p> </body> </html>
Pour aller plus loin...
Possibilité de chaîner les templates
Exemple de page template utilisant elle-même un template : ma_page_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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <ui:composition template="/template.xhtml"> <ui:define name="titre">Titre de ma page en dur</ui:define> <ui:define name="contenu"> <div class="style-header"><ui:insert name="header" /></div> <div class="style-texte"><ui:insert name="texte" /></div> <div class="style-footer"><ui:insert name="footer" /></div> </ui:define> </ui:composition> </html>
Exemple de page utilisant ma_page_template.xhtml : mon_autre_page.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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html"> <ui:composition template="/ma_page_template.xhtml"> <ui:define name="header"> Mon header </ui:define> <ui:define name="texte"> Texte, formulaires etc. </ui:define> <ui:define name="footer"> Mon footer </ui:define> </ui:composition> </html>
Résultat obtenu :
<!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://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:t="http://myfaces.apache.org/tomahawk"> <head> <title>Titre de ma page en dur</title> </head> <body> <p> <div class="style-header">Mon header</div> <div class="style-texte">Texte, formulaires etc.</div> <div class="style-footer">Mon footer</div> </p> </body> </html>
Essayer de ne pas déclarer <ui:define name="titre">Titre de ma page</ui:define> dans ma_page_template.xhtml et de l'ajouter dans mon_autre_page.xhtml et voir si ça fonctionne.
Possibilité de créer des composants
Création du composant
Un composant est une composition dans /webapp/WEB-INF/jsf/components/ : monInputText.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://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"> <ui:composition> <h:outputText value="#{titre}"/> : <h:inputText value="#{valeur}"/> </ui:composition> </html>
Création du taglib dans /webapp/WEB-INF/jsf/esup-commons.taglib.xml
<?xml version="1.0"?> <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "facelet-taglib_1_0.dtd"> <facelet-taglib> <namespace>http://commons.esup-portail.org</namespace> <tag> <tag-name>monInputText</tag-name> <source>/monInputText.xhtml</source> </tag> </facelet-taglib>
Déclaration
On déclarera le taglib dans un élément <context-param> de /webapp/WEB-INF/web.xml
<context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/esup-commons.taglib.xml </param-value> </context-param>
Utilisation du composant
<!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:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:e="http://commons.esup-portail.org"> <head> <title>Ma page</title> </head> <body> <f:view> <e:monInputText titre="Nom du champs" valeur="#{Controller.field}"/> </f:view> </body> </html>