Reusable CRUD Action Buttons through Facelets Composition
This article will follow you through reducing the seam gen'd Action Buttons for CRUD operations into a single reusable tag.
Original xhtml
<div class="actionButtons"> <h:commandButton id="save" value="Save" action="#{customerHome.persist}" rendered="#{!customerHome.managed}"></h:commandButton> <h:commandButton id="update" value="Save" action="#{customerHome.update}" rendered="#{customerHome.managed}"></h:commandButton> <h:commandButton id="delete" value="Delete" action="#{customerHome.remove}" rendered="#{customerHome.managed}"></h:commandButton> <s:button id="done" value="Done" propagation="end" view="/customerList.xhtml" rendered="#{customerHome.managed}"></s:button> <s:button id="cancel" value="Cancel" propagation="end" view="/customerList.xhtml" rendered="#{!customerHome.managed}"></s:button> </div>
New xhtml
<my:actionButtons backingBean="#{customerHome}" searchPage="/customerList.xhtml" ></my:actionButtons>
It can't get much easier than this, for use on another CRUD based page just replace the values of the backingBean and searchPage attributes.
Use - customer.xhtml
Add xmlns:my="http://my.com/jsf/my" to your namespace definitions
Replace the original xhtml with the new xhtml and change the backingBean and searchPage where necessary
Facelets Composition source - actionButtons.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:f="http://java.sun.com/jsf/core" xmlns:c="http://java.sun.com/jstl/core" xmlns:s="http://jboss.com/products/seam/taglib"> <ui:composition> <c:if test="${empty create}"> <c:set var="create" value="persist" ></c:set> </c:if> <c:if test="${empty update}"> <c:set var="update" value="update" ></c:set> </c:if> <c:if test="${empty delete}"> <c:set var="delete" value="remove" ></c:set> </c:if> <c:if test="${empty managed}"> <c:set var="managed" value="managed" ></c:set> </c:if> <div class="actionButtons"> <h:commandButton id="create" value="Create" action="#{backingBean[create]}" rendered="#{!backingBean[managed]}"></h:commandButton> <h:commandButton id="update" value="Update" action="#{backingBean[update]}" rendered="#{backingBean[managed]}"></h:commandButton> <h:commandButton id="delete" value="Delete" action="#{backingBean[delete]}" rendered="#{backingBean[managed]}"></h:commandButton> <s:button id="done" value="Done" propagation="end" view="#{searchPage}" rendered="#{backingBean[managed]}"></s:button> <s:button id="cancel" value="Cancel" propagation="end" view="#{searchPage}" rendered="#{!backingBean[managed]}"></s:button> </div> </ui:composition> </html>
The c:if's allow me to eliminate a lot of the otherwise necessary attributes for my:actionButtons. This way I can define default behavior following the most common usage.
Wiring
These files live in WEB-INF.
facelets taglib - my.taglib.xml
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "http://java.sun.com/dtd/faces-taglib_1_0.dtd"> <facelet-taglib> <namespace>http://my.com/jsf/my</namespace> <tag> <tag-name>actionButtons</tag-name> <source>actionButtons.xhtml</source> </tag> </facelet-taglib>
Web.xml - web.xml
... <context-param> <param-name>facelets.LIBRARIES</param-name> <param-value>/WEB-INF/my.taglib.xml</param-value> </context-param> ...
Comments