2 Replies Latest reply on Jun 26, 2008 10:53 AM by Oliver Pütter

    Rerender on scrollableDataTable with a changed model does no

    Oliver Pütter Newbie

      Hello,

      I am dealing with the following problem.

      I use a scrollable data table with an underlying Data Model in my backing bean. The model class implements the method loadData(..) which fetches the requested elements from a list of data.

      public List loadData(int startRow, int endRow, SortOrder sortOrder)
      {
       System.out.println("Loading from " + startRow + " to " + endRow);
       return vendors.subList(startRow, endRow);
      }
      


      The amount of data to represent in the table is very large so I decided to specify the row-Attribute with a value of 10. This makes the table to load the data incrementally. Without this attribute performance is bad.

      <rich:scrollableDataTable
       sortMode="single"
       rows="10"
       id="vendorTable"
       selectedClass="tableSelection"
       value="#{vendorBean.vendorModel}"
       var="vendor"
       height="120px"
       binding="#{vendorBean.htmlScrollableDataTable}"
       rowKeyVar="rkv"
       selection="#{vendorBean.selectedRows}">
       ...
      


      So far, so good. Because of the large amount of data I added an input field and an a4j-commandButton to implement a filter on the data. When pressing the button an ajax request takes the value from the field and the backing bean recalculates the model. When the request is complete the table is rerendered and loadData crashes because of invalid indexes (startRow > endRow). This happens only when the filter button is pressed after scrolling the table down and further data was loaded from the model, so startRow is greater than zero.

      I read that this is a bug, because startRow should be set to zero. Someone implemented a phase listener to call setFirst(0) and setRowIndex(0) on the table whenever this component is rendered. This workaround does not work for me, because it seems that the phase listener is not called on an ajax rerender.

      When putting the following code at the beginning of the filter method, resetting the starting row to zero works but the table shows a strange behaviour. For a second you can see the filtered data without table headers. After that when rendering the headers the table is empty.

      UIComponent comp = FacesContext.getCurrentInstance().getViewRoot().findComponent("vendor:vendorTable");
      
      if (comp instanceof UIData)
      {
       UIData data = (UIData) comp;
       data.setFirst(0);
       data.setRowIndex(0);
      }
      


      Has anyone an idea to make this work? This is actually a complete show stopper for our project.

      Thanks a lot.



        • 1. Rerender on scrollableDataTable with a changed model does no
          Oliver Pütter Newbie

          Meanwhile I managed to prevent the table from crashing when filtering after scrolling the table. This is nearly the workaround I mentioned before but the solution is still not completely available.

          I implemented a phase listener in the following way:

          
          public class RenderResponsePhaseListener implements PhaseListener
          {
           private PhaseId phase = PhaseId.RENDER_RESPONSE;
          
           public void beforePhase(PhaseEvent e)
           {
           UIComponent comp = FacesContext.getCurrentInstance().getViewRoot().findComponent("vendor:vendorTable");
          
           if (comp != null && comp instanceof UIData)
           {
           UIData data = (UIData) comp;
           ScrollableTableDataModel stdm = (ScrollableTableDataModel)data.getValue();
          
           if (data.getFirst() > stdm.getRowCount())
           {
           data.setFirst(0);
           }
           }
           }
          
           public void afterPhase(PhaseEvent e)
           {
           }
          
           public void setPhase(PhaseId phase)
           {
           this.phase = phase;
           }
          
           public PhaseId getPhaseId()
           {
           return phase;
           }
          }
          
          


          Now the value for the attribute "first" is correctly set when rerendering the table on a changed model.

          The filtered values appear for a few milliseconds and after rendering the headers the table is completely empty with no grid.

          Seems that something is still invalid.

          But what?

          Btw: The phase listener is always triggered with the rerendering that origins from the ajax requests. In my previous post I was wrong.

          Please help!

          • 2. Re: Rerender on scrollableDataTable with a changed model doe
            Oliver Pütter Newbie

            After all I did it.

            ...
            current.setFirst(0);
            try
            {
             current.encodeBegin(FacesContext.getCurrentInstance());
            }
            catch(Exception e)
            {
             e.printStackTrace();
            }
            ...
            


            This solves the refreshing problem. Now everything works fine.:-)

            Cheers.