2 Replies Latest reply on Nov 27, 2012 2:51 AM by jmsjr

    Selection with rich:extendedDataTable via <a4j:ajax listener> not called when an <rich:table required="true"> is in the table

    jmsjr

      RichFaces 4.2.3-Final

      JBoss 7.1.1 (Brontes)

       

      I need to have input elements within the each row of the a rich:extendedDataTable. However, as soon as I have any input field in a rich:column, the a4j:ajax call is no longer made.

       

      Here is a sample where the selection DOES work, as everything inside a rich:column is just a h:outputText

       

      testExtendedDataTable.xhtml

       

      {code}

      <!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:ui="http://java.sun.com/jsf/facelets"

            xmlns:rich="http://richfaces.org/rich"

            xmlns:a4j="http://richfaces.org/a4j">

       

       

      <h:head></h:head>

      <body>

          <h:form id="aForm">

              <rich:extendedDataTable id="sampleTable" value="#{tableBean.rows}" var="row"

                 selectionMode="single"

                 selection="#{tableBean.selection}">

                 <a4j:ajax execute="sampleTable" event="selectionchange" render="outputSelection" listener="#{tableBean.selectionListener}"/>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Name"/>

                     </f:facet>

                     <h:outputText value="#{row.name}"/>

                 </rich:column>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Required"/>

                     </f:facet>

                     <h:outputText value="#{row.required}"/>

                 </rich:column>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Some Date"/>

                     </f:facet>

                     <h:outputText value="#{row.someDate}"/>

                 </rich:column>

              </rich:extendedDataTable>

       

              <a4j:outputPanel id="outputSelection">

                  Current Selection: <h:outputText value="#{tableBean.selectedRow.name}" />

              </a4j:outputPanel>

          </h:form>

      </body>

      </html>

       

      {code}

       

       

       

      Here is the backing bean which stores the collection ( The sample code was based off the showcases in RichFaces )

       

       

      {code}

      package test;

       

       

      import java.io.Serializable;

      import java.util.ArrayList;

      import java.util.Collection;

      import java.util.Date;

      import java.util.List;

       

       

      import javax.annotation.PostConstruct;

      import javax.faces.bean.ManagedBean;

      import javax.faces.bean.ViewScoped;

      import javax.faces.event.AjaxBehaviorEvent;

       

       

      import org.richfaces.component.UIExtendedDataTable;

       

       

      @ManagedBean

      @ViewScoped

      public class TableBean implements Serializable {

       

                private List<RowBean> rows;

                private Collection<Object> selection;

                private RowBean selectedRow;

       

                public RowBean getSelectedRow() {

                          return selectedRow;

                }

       

       

                public void setSelectedRow(RowBean selectedRow) {

                          this.selectedRow = selectedRow;

                }

       

       

                public List<RowBean> getRows() {

                          return rows;

                }

       

       

                public void setRows(List<RowBean> rows) {

                          this.rows = rows;

                }

       

          public Collection<Object> getSelection() {

              return selection;

          }

       

          public void setSelection(Collection<Object> selection) {

              this.selection = selection;

          }

       

          public void selectionListener(AjaxBehaviorEvent event) {

              UIExtendedDataTable dataTable = (UIExtendedDataTable) event.getComponent();

              Object originalKey = dataTable.getRowKey();

              setSelectedRow( null );

              for (Object selectionKey : selection) {

                  dataTable.setRowKey(selectionKey);

                  if (dataTable.isRowAvailable()) {

                            setSelectedRow( (RowBean) dataTable.getRowData() );

                  }

              }

              dataTable.setRowKey(originalKey);

          }  

       

       

                @PostConstruct

                public void init() {

                          setRows( new ArrayList<RowBean>() );

       

                          RowBean row1 = new RowBean();

                          row1.setName("John Smith");

                          row1.setRequired(true);

                          row1.setSomeDate(null);

       

                          RowBean row2 = new RowBean();

                          row2.setName("Jane Smith");

                          row2.setRequired(false);

                          row2.setSomeDate(new Date());

       

                          getRows().add(row1);

                          getRows().add(row2);

                }

      }

      {code}

       

       

      Here is the backing bean which stores the row:

       

       

      {code}

      package test;

       

       

      import java.io.Serializable;

      import java.util.Date;

       

       

      import javax.faces.bean.ManagedBean;

      import javax.faces.bean.ViewScoped;

       

       

      @ManagedBean

      @ViewScoped

      public class RowBean implements Serializable {

       

                public String           name;

                public boolean          required;

                public Date                    someDate;

       

                public String getName() {

                          return name;

                }

                public boolean isRequired() {

                          return required;

                }

                public Date getSomeDate() {

                          return someDate;

                }

                public void setName(String name) {

                          this.name = name;

                }

                public void setRequired(boolean required) {

                          this.required = required;

                }

                public void setSomeDate(Date someDate) {

                          this.someDate = someDate;

                }

      }

      {code}

       

       

      Deploy, and selecting between the two rows will update the lower panel to show the currently selected row.

      However, if I change a rich:column so that it now has an h:selectBooleanCheckbox, or the date becomes a rich:calendar, then the selection listener specified by the listener attribute in a4j:ajax is no longer called:

       

       

      {code}

      <!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:ui="http://java.sun.com/jsf/facelets"

            xmlns:rich="http://richfaces.org/rich"

            xmlns:a4j="http://richfaces.org/a4j">

       

       

      <h:head></h:head>

      <body>

          <h:form id="aForm">

              <rich:extendedDataTable id="sampleTable" value="#{tableBean.rows}" var="row"

                 selectionMode="single"

                 selection="#{tableBean.selection}">

                 <a4j:ajax execute="sampleTable" event="selectionchange" render="outputSelection" listener="#{tableBean.selectionListener}"/>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Name"/>

                     </f:facet>

                     <h:outputText value="#{row.name}"/>

                 </rich:column>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Required"/>

                     </f:facet>

                     <h:selectBooleanCheckbox id="contactIntentionToClaim" value="#{row.required}"/>

                 </rich:column>

                 <rich:column>

                     <f:facet name="header">

                         <h:outputText value="Some Date"/>

                     </f:facet>

                     <h:outputText value="#{row.someDate}"/>

                 </rich:column>

              </rich:extendedDataTable>

       

              <a4j:outputPanel id="outputSelection">

                  Current Selection: <h:outputText value="#{tableBean.selectedRow.name}" />

              </a4j:outputPanel>

          </h:form>

      </body>

      </html>

      {code}

       

       

      Putting in logging messages into TableBean.selectionListener() method shows that the method is no longer being called.

       

      Anyone seen this before ?

        • 1. Re: Selection with rich:extendedDataTable via <a4j:ajax listener> not called when an input field is in the table
          jmsjr

          Have to reply to own post, but basically:

           

          1) The second xhtml above is actually working. The xhtml when the ajax listener is NOT called is as follows:

           

           

          {code}

          <!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:ui="http://java.sun.com/jsf/facelets"

                xmlns:rich="http://richfaces.org/rich"

                xmlns:a4j="http://richfaces.org/a4j">

           

           

          <h:head></h:head>

          <body>

              <h:form id="aForm">

                  <rich:extendedDataTable id="sampleTable" value="#{tableBean.rows}" var="row"

                     selectionMode="single"

                     selection="#{tableBean.selection}">

                     <a4j:ajax execute="sampleTable" event="selectionchange" render="outputSelection" listener="#{tableBean.selectionListener}"/>

                     <rich:column>

                         <f:facet name="header">

                             <h:outputText value="Name"/>

                         </f:facet>

                         <h:outputText value="#{row.name}"/>

                     </rich:column>

                     <rich:column>

                         <f:facet name="header">

                             <h:outputText value="Required"/>

                         </f:facet>

                         <h:selectBooleanCheckbox id="requiredColumn" value="#{row.required}" required="true"/>

                         <!-- h:outputText value="#{row.required}"/-->

                     </rich:column>

                     <rich:column>

                         <f:facet name="header">

                             <h:outputText value="Some Date"/>

                         </f:facet>

                         <rich:calendar id="someDate"

                              value="#{row.someDate}"

                              enableManualInput="true"

                              showApplyButton="false"

                              required="true"

                              requiredMessage="Date is required"

                              datePattern="dd/MM/yyyy"

                         />

                         <!-- h:outputText value="#{row.someDate}"/-->

                     </rich:column>

                  </rich:extendedDataTable>

           

                  <a4j:outputPanel id="outputSelection">

                      Current Selection: <h:outputText value="#{tableBean.selectedRow.name}" />

                  </a4j:outputPanel>

              </h:form>

          </body>

          </html>

          {code}

           

           

          2) If you then REMOVE the required="true" attribute from the rich:calendar, then the selection works again ( Ajax calles the listener method ).

           

          Still don't know WHY it is not being called, but at least there is now more information.

           

          Updated thread title to reflect the root cause.

          • 2. Re: Selection with rich:extendedDataTable via <a4j:ajax listener> not called when an input field is in the table
            jmsjr

            OK .. By adding <rich:mesages/>, I can now see that the validation is actually failing because we now have required="true", so that the listener is not actually called.

            That makes sense I guess.

             

            The workaround is to have immediate="true" in the <a4j:ajax> element, although you will still get the <rich:messages> shown.

            Is there anyway of skipping all validation on all of the inputs .. except when you submit the form via a commandButton ?