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