3 Replies Latest reply on Apr 3, 2009 4:46 PM by jeremygood

    s:decorate with a4j:support -- invalid and required context variables not set

      I 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:



      1. error message appears to the right of the field

      2. the field label turns red

      3. 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

        • 1. Re: s:decorate with a4j:support -- invalid and required context variables not set
          gonorrhea

          Did you omit the <h:form> or <rich:form> tags on purpose in your main xhtml?


          Try this for your edit.xhtml:


          <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">
                          
                  <s:label styleClass="name #{invalid?'errors':''}">
                      <ui:insert name="label"/>
                      <s:span styleClass="required" rendered="#{required}">*</s:span>
                  </s:label>
                  
                  <span class="value #{invalid?'errors':''}">
                      <s:validateAll>
                          <ui:insert/>
                      </s:validateAll>
                  </span>
                          
                  <s:message styleClass="errors"/>        
              
          </ui:composition>



          As per Practical RF book:




          Using bypassUpdates
          When just validating form values, set bypassUpdates="true". When set to true, the Update
          Model and Invoke Application phases will not be invoked, improving response time.

          It should be ok to use that attribute, but I would remove to see how it behaves...

          • 2. Re: s:decorate with a4j:support -- invalid and required context variables not set

            Removing bypassUpdates=true and ajaxSingle=true has no effect. The results are the same.


            My form tag is in template.xhtml, sorry forgot about that. I've included it below.


            In your version of edit.xhtml, you've left out the error.gif and the a4j:outputPanel. Was that intentional? I don't want to remove the image. And, without the a4j:outputPanel, the error message doesn't even show up when an invalid field loses focus (so none of the three error indicators appear). I've modified it with some of your suggestions as follows, but I still have the same results:


            <!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">
                  <s:label styleClass="label #{invalid ? 'errors' : ''}">
                     <ui:insert name="label"/>
                     <s:span styleClass="required" rendered="#{required}">*</s:span>
                  </s:label>
                  <span class="value">
                     <s:validateAll>
                        <ui:insert/>
                     </s:validateAll>
                  </span>
                  <h:graphicImage value="/img/error.gif"
                      rendered="#{invalid}" styleClass="errors"/>
                      <s:message styleClass="errors"/>
               </a4j:outputPanel>
            </ui:composition>
            



            and here's the template.xhtml (I've tried it with both h:form and a4j:form, it doesn't make any difference.):


            <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
            <f:view contentType="text/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:a4j="http://richfaces.org/a4j"
               xmlns:s="http://jboss.com/products/seam/taglib">
            
            <html>
            <head>
               <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
               <title>Restaurapps: Coupon Management System (rCMS)</title>
               <link href="css/screen.css" rel="stylesheet" type="text/css" />
               <link href="css/rich-calendar.css" rel="stylesheet" type="text/css" />
               <link href="css/rich-togglePanel.css" rel="stylesheet" type="text/css" />
            </head>
            <body>
            
               <div id="document">
                  <div id="header">
                     <div id="title">Restaurapps: Coupon Management System</div>
                     <div id="status">
                        Welcome #{definer.firstName} #{definer.lastName}
                           | <s:link id="logout" action="#{identity.logout}" value=" Logout"/>
                     </div>
                  </div>
                  <div id="container">
                     <div id="pageTitle"><ui:insert name="pageTitle"/></div>
                     <div id="sidebar">
                        <ui:insert name="sidebar"/>
                     </div>
                     <a4j:form id="contentForm">
                        <div id="content">
                           <ui:insert name="content"/>
                        </div>
                        <div id="wizard">
                           <s:div styleClass="wizardPrevButtons">
                              <ui:insert name="wizardPrev"/>
                           </s:div>
                           <s:div styleClass="wizardCancelButtons">
                              <ui:insert name="wizardCancel"/>
                           </s:div>
                           <s:div styleClass="wizardNextButtons">
                               <ui:insert name="wizardNext"/>
                           </s:div>
                        </div>
                     </a4j:form>
                  </div>
                  <div id="footer"><span id="footerText">© 2009 Restaurapps</span></div>
               </div>
            </body>
            </html>
            </f:view>
            

            • 3. Re: s:decorate with a4j:support -- invalid and required context variables not set

              Ok, I got the answer on the richfaces forum.


              It's a stupid mistake on my part.


              I left the reRender tag off the a4j:support tag.


              Adding reRender=shortNameField solves all my problems.


              Thanks,
              Jeremy