Replacement for s:decorate in Seam 3
Join the DZone community and get the full member experience.
Join For FreeI've been doing a gap analysis for our migration from Seam 2 to Seam 3, and I was dismayed to find that the <s:decorate> tag is gone! In Seam 2, you create a template like this:
<ui:composition 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:s="http://jboss.com/products/seam/taglib"> <div class="prop"> <s:label styleClass="nameEdit #{invalid?'errors':''}"> <s:span styleClass="required" rendered="#{required}">*</s:span> <ui:insert name="label"/> </s:label> <span class="value #{invalid?'errors':''}"> <s:validateAll> <ui:insert/> </s:validateAll> </span> <span class="error"> <h:graphicImage value="/img/error.gif" rendered="#{invalid}" styleClass="errors"/> </span> </div> </ui:composition>
And then reference it using <s:decorate>
<s:decorate template="edit.xhtml"> <ui:define name="label">Country:</ui:define> <h:inputText value="#{location.country}" required="true"/> </s:decorate>
And now required fields are noted with an asterisk (*), all fields are
automatically validated, and when they have errors, a special style is
applied and the error message appears to the right of the field:
Note: this is all documented in Section 33.1.13 of the Seam 2 reference.
Pretty slick! I definitely need this functionality when I migrate to Seam 3, but the <s:decorate> tag is gone, and I had a hard time finding a replacement.
Replacing with UIInputContainer
Fortunately, a close replacement
actually exists in Seam 3's Faces module... it just isn't described as
such! Seam Faces provides a component called UIInputContainer. When this is combined with a JSF 2 composite component, you can get the same functionality.
First, create your composite component. I created mine at WebContent/resources/orr/decorate.xhtml:
<?xml version="1.0"?> <!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:h="http://java.sun.com/jsf/html" xmlns:composite="http://java.sun.com/jsf/composite"> <composite:interface componentType="org.jboss.seam.faces.InputContainer" /> <composite:implementation> <div> <h:outputLabel id="label" value="#{cc.attrs.label}:" styleClass="#{cc.attrs.invalid ? 'invalid' : ''}"> <h:outputText styleClass="required" rendered="#{cc.attrs.required}" value="*" /> </h:outputLabel> <!-- h:panelGroup is a workaround for a JSF bug, see http://java.net/jira/browse/JAVASERVERFACES-1991 --> <h:panelGroup styleClass="value #{invalid?'errors':''}" > <composite:insertChildren /> </h:panelGroup> <h:message id="message" errorClass="invalid message" rendered="#{cc.attrs.invalid}" /> </div> </composite:implementation> </html>
Since I put the composite component in WebContent/resources/orr/decorate.xhtml, the namespace is http://java.sun.com/jsf/composite/orr and the tag name is decorate.
Now use this new tag in your Facelets page:
<!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:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:o="http://java.sun.com/jsf/composite/orr"> <o:decorate label="Country:"> <h:inputText value="#{location.country}" required="true"/> </o:decorate>
And that's it! This will generate roughly the same output and behavior as Seam 2's <s:decorate> tag. So all along, there was a pretty good replacement, but either this wasn't made clear anywhere, or my Google skills aren't quite as good as I think. I imagine this would be documented in JBoss's Seam 2 to Seam 3 migration guide, if such a thing existed...
Published at DZone with permission of Jeremiah Orr, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments