s:decorate with a4j:support -- invalid and required context variables not set
jeremygood Apr 2, 2009 7:31 PMI am attempting to implement live validation on an input form using Seam's s:decorate, RichFaces' a4j:outputPanel and a4j:support, and Hibernate's field-level validation (@Length) as outlined in Seam in Action, pp 89-90.
There are three things that should happen on any error:
- error message appears to the right of the field
- the field label turns red
- an error.gif image appears in front of the error message
When a field with a Hibernate field-level validation error loses focus, the error message appears. However, the other two items do not show up.
All three items DO show up when the form is submitted with an error.
The items not showing up on ajax validation are controlled by the #{invalid} context variable. Note also that in the first image, the asterisks next to the Active and Short Name labels are missing. The asterisks are rendered according to the #{required} context variable.
According to the Seam Reference Guide, section 32.1.3.1 on s:decorate
#{invalid} and #{required} are available inside s:decorate; #{required} evaluates to true if you have set the input component being decorated as required, and #{invalid} evaluates to true if a validation error occurs.
Here are the appropriate code snippets:
The view:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <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" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" template="template.xhtml"> <ui:define name="content"> <div class="section"> <s:div id="fieldsPanel"> <s:div id="fieldsPanelInterior"> <rich:simpleTogglePanel switchMode="client" label="Coupon Identification" headerClass="togglePanelHeader" opened="false"> ... <s:decorate id="shortNameField" template="edit.xhtml"> <ui:define name="label">Short Name</ui:define> <h:inputText styleClass="inField" id="shortName" value="#{editCoupon.shortName}" style="width: 180px;" required="true"> <a4j:support id="shortNameCheck" event="onblur" ajaxSingle="true" bypassUpdates="true"/> <s:validate/> </h:inputText> </s:decorate> ... </rich:simpleTogglePanel> </s:div> </s:div> </div> </ui:define> </ui:composition>
The view field template (edit.xhtml):
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:rich="http://richfaces.org/rich" xmlns:a4j="http://richfaces.org/a4j" xmlns:h="http://java.sun.com/jsf/html"> <a4j:outputPanel ajaxRendered="true"> <div class="label #{invalid ? 'errors' : ''}"> <s:label> <s:span><ui:insert name="label"/></s:span> <s:span styleClass="required" rendered="#{required}">*</s:span> </s:label> </div> <span> <s:validateAll> <ui:insert styleClass="value #{invalid ? 'errors' : ''}"/> </s:validateAll> </span> <span class="error"> <h:graphicImage value="/img/error.gif" rendered="#{invalid}" styleClass="errors"/> <s:message styleClass="errors"/> </span> </a4j:outputPanel> </ui:composition>
The entity bean:
@Entity @Name("coupon") public class Coupon implements Serializable { private Long id; private String shortName; ... @Id @GeneratedValue public Long getId() { return id; } public void setId(Long id) { this.id = id; } @Length(min=2, max=32) @NotNull public String getShortName() { return shortName; } public void setShortName(String shortName) { this.shortName = shortName; } ...
Here is the generated HTML showing the onblur tag (I added line breaks between tags/attributes for readability):
<div id="contentForm:shortNameField"> <span id="contentForm:shortNameField:j_id28"> <div class="label"> <label for="contentForm:shortNameField:shortName"> <span id="contentForm:shortNameField:j_id31">Short Name</span> </label> </div> <span> <input style="width: 180px;" onblur="A4J.AJAX.Submit('_viewRoot','contentForm',event,{'parameters':{'ajaxSingle':'contentForm:shortNameField:shortName','contentForm:shortNameField:shortNameCheck':'contentForm:shortNameField:shortNameCheck'} ,'actionUrl':'/rCMS/editCoupon.seam','control':this} )" class="inField" value="$5.00 off deal March" name="contentForm:shortNameField:shortName" id="contentForm:shortNameField:shortName" type="text"> </span> <span class="error"></span> </span> </div>
Please let me know if you have any ideas about this. Also, let me know if you have code that successfully evaluates #{required} and #{invalid} during live validation.
Thanks very much for your help,
Jeremy Goodell