There are several reasons to use Facelets, like:
- Problems in JSF 1.1 “Content Interweaving”
- lightweight Templating Framwork (XHTML-based templates)
- very friendly to designers (similar to Tapestry)
- performance
- JSF 1.2 w/o JavaEE 5 Container
Another is the very easy way of creating custom JSF components. In plain JSF you need these artifacts:
- a lot of Java (Component, Renderer, JSP-Tag Class)
- some XML (faces-config, TLD)
With Facelets, it is this:
- XHTML file
- Facelets Taglib XML file (very simple syntax)
With Facelets it is very easy to create sexy components, using 3rd party JavaScript libraries, such as Dojo Toolkit. The XHTML file contains all the markup want. The “taglib” is the glue code between the XHTML file and the user’s page, where a page author is using the (new) component.
The Dojo Toolkit contains lot of cool “components”, such as an accordion. It is not hard to make your layout (<div> elements) become a “AccordionContainer”, that contains several “AccordionPane” components, as the previews link shows. But every time reusing this, you repeat your self. So… you finally want a (jsf) component. Easy with Facelets.
All you need is two XHTML files (one for the container and one for the pane) and a little bit of XML to wire the two tags to the new components.
The container xhtml:
<div
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets">
<link rel="stylesheet" type="text/css"
href="dtk/dijit/themes/tundra/tundra.css" />
<script type="text/javascript"
src="http://o.aolcdn.com/dojo/1.0.0/dojo/dojo.xd.js"
djConfig="parseOnLoad: true"></script>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dijit.layout.AccordionContainer");
</script>
<div dojoType="dijit.layout.AccordionContainer"
duration="#{duration}" style="#{style}">
<ui:insert/>
</div>
</div>
Simply import the required CSS and JavaScript files and make the <div> element a “AccordionContainer” by using the dojoType attribute. The value for the attributes duration and style is provided with a ValueExpression. The user of the accordionContainer tag has to specify the correct value. Inside the <div> element there is a <ui:insert />. This allows us to nest other content (such as the later described pane component) inside the accordion.The pane xhtml:
<div xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
dojoType="dijit.layout.AccordionPane"
title="#{title}">
<ui:insert/>
</div>
This one is very simple, just a <div> that is representing the AccordionPane and a <ui:insert/> to nest content. Please note that this “component” doesn’t need to import CSS or JavaScript files. Why? Because it is only used inside the accordion which is already loading the needed files.The XML for the “taglib”:
<facelet-taglib>
<namespace>
http://wessendorf.net/kickstart
</namespace>
<tag>
<tag-name>accordionContainer</tag-name>
<source>facelets/components/accordionContainer.xhtml</source>
</tag>
<tag>
<tag-name>accordionPane</tag-name>
<source>facelets/components/accordionPane.xhtml</source>
</tag>
</facelet-taglib>
The taglib file is pretty trivial. It just contains a bunch of tags and points to the source code of the component, the location of the XHTML files.The finally result (the page, that uses these new components) looks like:
<mw:accordionContainer duration="250"
style="margin-right: 30px; width: 400px; height: 300px; overflow: hidden">
<mw:accordionPane title="html content">
<p>Hello</p>
</mw:accordionPane>
<mw:accordionPane title="some more html content">
<ul>
<li>hey!</li>
</ul>
</mw:accordionPane>
<mw:accordionPane title="JSF component content">
<tr:inputDate />
</mw:accordionPane>
</mw:accordionContainer>
It is possible to mix content such as regular HTML or some other JSF components, like the <tr:inputDate> component from Trinidad.Very easy and straightforward to add to your project!I updated FacesGoodies to ship this example (only via SVN).
