2 Replies Latest reply on Jun 9, 2008 10:33 AM by mike_edmiston

    DataTable losing input values when validation fails

    mike_edmiston

      I've got a form containing an input text and a rich datatable containing an input text per row. When the form is submitted and a validation error occurs outside the datatable, all entries made inside the datatable except the last one are lost.

      I took a look at the RichFaces code and it looks like the problem is in the UIDataAdaptor.encodeBegin(FacesContext) method. This method calls UIDataAdaptor.keepSaved(FacesContext) to determine if the childState map is cleared. The keepSaved method only returns true if there is a validation error on any of the child components inside the datatable. In my case, I have validation errors on components outside the datatable so it returns false. It seems like keepSaved should return true if any components in the entire form are invalid, not just the ones inside the datatable.

      Here is some simple code that recreates the problem. To see the problem, leave the first input field, "Parent Name", blank and enter values for the two rows in the datatable. Hit save. The page will refresh, you will get a validation error that parent name is required but the first value entered in the table is lost.

      Environment: RichFaces 3.2.0 SR1, JSF RI 1.2, Seam 2.0 GA

      xhtml:

      <html xmlns="http://www.w3.org/1999/xhtml"
       xmlns:h="http://java.sun.com/jsf/html"
       xmlns:rich="http://richfaces.ajax4jsf.org/rich">
      
       <h:form>
       Parent Name: <h:inputText id="parentInput" value="#{backingBean.parentName}" required="true"/> <h:message style="color: red" for="parentInput"/>
       <br/><br/>
       <rich:dataTable var="child" value="#{backingBean.children}">
       <rich:column>
       Child Name: <h:inputText value="#{child.name}"/>
       </rich:column>
       </rich:dataTable>
      
       <h:commandButton value="Save" />
       </h:form>
      
      </html>
      


      BackingBean.java:

      import java.util.ArrayList;
      import java.util.List;
      
      import org.jboss.seam.annotations.Name;
      
      @Name("backingBean")
      public class BackingBean {
      
       private String parentName;
       private List<Child> children = new ArrayList<Child>();
      
       public BackingBean() {
       // Start off with two rows
       children.add(new Child());
       children.add(new Child());
       }
      
       public String getParentName() {
       return parentName;
       }
      
       public void setParentName(String name) {
       this.parentName = name;
       }
      
       public List<Child> getChildren() {
       return children;
       }
      
       public void setChildren(List<Child> values) {
       this.children = values;
       }
      
      
       public class Child {
       private String name;
      
       public String getName() {
       return name;
       }
      
       public void setName(String name) {
       this.name = name;
       }
      
      
       }
      }