Replacement for s:decorate in Seam 3
I'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...
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





