2 Replies Latest reply on Jan 14, 2009 10:46 AM by wciesiel

    Problem with filtered scrollabla dataTable

      Hi there,

      I am trying to create a scrollable (rich:dataScroller) dataTable (rich:dataTable) controlled by a form with several filtering controls (some date ranges etc).

      Important note - It's RichFaces 3.1.6... I'm stuck with JBoss 4.0.x and cant move to JSF 1.2 yet :-(

      But back to the point. Implementation looks like this:

      page contents

      <h:form id="txForm">
       ... some controls, like this one:
       <rich:calendar value="#{dataProvider.fromDate}"
       datePattern="dd/MM/yyyy" popup="true" cellWidth="24px"
       cellHeight="22px" style="width:200px" />
      
       .. then apply button:
       <a4j:commandButton value="apply filter" reRender="txForm" />
       .. then data scroller
       <rich:datascroller for="txTable" />
       .. then table itself
       <rich:dataTable id="txTable" value="#{dataProvider}"
       var="tx" width="100%" rows="10">
       ...
       </rich:dataTable>
      


      Pretty simple until now, isnt't it? dataProvider extends SerializableDataModel via class like this:

      public abstract class PaginatingDataModel<OBJ, ID> extends SerializableDataModel {
       /** */
       private static final long serialVersionUID = 2954923950179861809L;
       /** */
       protected ID currentPk;
       /** */
       protected boolean descending = true;
       /** */
       protected String sortField = getDefaultSortField();
       /** */
       protected boolean detached = false;
       /** */
       protected List<ID> wrappedKeys = new ArrayList<ID>();
       /** */
       protected Integer rowCount;
       /** */
       protected Map<ID, OBJ> wrappedData = new HashMap<ID, OBJ>();
      
       /**
       * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
       */
       @Override
       public Object getRowKey() {
       return currentPk;
       }
      
       /**
       * @see org.ajax4jsf.model.ExtendedDataModel#setRowKey(java.lang.Object)
       */
       @SuppressWarnings("unchecked")
       @Override
       public void setRowKey(final Object key) {
       this.currentPk = (ID) key;
       }
      
       /**
       * @see org.ajax4jsf.model.SerializableDataModel#update()
       */
       @Override
       public void update() {
       if (getSortFieldObject() != null) {
       final String newSortField = getSortFieldObject().toString();
       if (newSortField.equals(sortField)) {
       descending = !descending;
       }
       sortField = newSortField;
       }
       detached = false;
       }
      
       /**
       * @return Object
       */
       protected Object getSortFieldObject() {
       final FacesContext context = FacesContext.getCurrentInstance();
       final Object sortFieldObject = context.getExternalContext().getRequestParameterMap().get("sortField");
       return sortFieldObject;
       }
      
       /**
       * @param sortField
       */
       public void setSortField(final String sortField) {
       if (this.sortField.equals(sortField)) {
       descending = !descending;
       } else {
       this.sortField = sortField;
       }
       }
      
       /**
       * @return String
       */
       public String getSortField() {
       return sortField;
       }
      
       /**
       * @see org.ajax4jsf.model.ExtendedDataModel#getSerializableModel(org.ajax4jsf.model.Range)
       */
       @Override
       public SerializableDataModel getSerializableModel(final Range range) {
       if (wrappedKeys != null) {
       detached = true;
       return this;
       }
       return null;
       }
      
       /**
       * @see javax.faces.model.DataModel#setRowIndex(int)
       */
       @Override
       public void setRowIndex(final int rowIndex) {
       throw new UnsupportedOperationException();
      
       }
      
       /**
       * @see javax.faces.model.DataModel#setWrappedData(java.lang.Object)
       */
       @Override
       public void setWrappedData(final Object data) {
       throw new UnsupportedOperationException();
      
       }
      
       /**
       * @see javax.faces.model.DataModel#getRowIndex()
       */
       @Override
       public int getRowIndex() {
       throw new UnsupportedOperationException();
       }
      
       /**
       * @see javax.faces.model.DataModel#getWrappedData()
       */
       @Override
       public Object getWrappedData() {
       throw new UnsupportedOperationException();
       }
      
       /**
       * @see org.ajax4jsf.model.ExtendedDataModel#walk(javax.faces.context.FacesContext,
       * org.ajax4jsf.model.DataVisitor, org.ajax4jsf.model.Range,
       * java.lang.Object)
       */
       @Override
       public void walk(final FacesContext context, final DataVisitor visitor, final Range range,
       final Object argument) throws IOException {
       final int firstRow = ((SequenceRange) range).getFirstRow();
       final int numberOfRows = ((SequenceRange) range).getRows();
       if (detached && getSortFieldObject() != null) {
       for (final ID key : wrappedKeys) {
       setRowKey(key);
       visitor.process(context, key, argument);
       }
       } else { // if not serialized, than we request data from data
       // provider
       wrappedKeys = new ArrayList<ID>();
       for (final OBJ object : findObjects(firstRow, numberOfRows, sortField, descending)) {
       wrappedKeys.add(getId(object));
       wrappedData.put(getId(object), object);
       visitor.process(context, getId(object), argument);
       }
       }
       }
      
       /**
       * @see javax.faces.model.DataModel#isRowAvailable()
       */
       @Override
       public boolean isRowAvailable() {
       if (currentPk == null) {
       return false;
       }
       if (wrappedKeys.contains(currentPk)) {
       return true;
       }
       if (wrappedData.entrySet().contains(currentPk)) {
       return true;
       }
       try {
       if (getObjectById(currentPk) != null) {
       return true;
       }
       } catch (final Exception e) {
      
       }
       return false;
       }
      
       /**
       * @see javax.faces.model.DataModel#getRowData()
       */
       @Override
       public Object getRowData() {
       if (currentPk == null) {
       return null;
       }
      
       OBJ object = wrappedData.get(currentPk);
       if (object == null) {
       object = getObjectById(currentPk);
       wrappedData.put(currentPk, object);
       }
       return object;
       }
      
       /**
       * @see javax.faces.model.DataModel#getRowCount()
       */
       @Override
       public int getRowCount() {
       if (rowCount == null) {
       rowCount = getNumRecords();
       }
       return rowCount;
       }
      
       /**
       *
       * @param object
       * @return U
       */
       public abstract ID getId(OBJ object);
      
       /**
       * @param firstRow
       * @param numberOfRows
       * @param sortField
       * @param descending
       * @return List<T>
       */
       public abstract List<OBJ> findObjects(int firstRow, int numberOfRows, String sortField, boolean descending);
      
       /**
       * @param id
       * @return T
       */
       public abstract OBJ getObjectById(ID id);
      
       /**
       * @return String
       */
       public abstract String getDefaultSortField();
      
       /**
       * @return int
       */
       public abstract int getNumRecords();
      }
      


      Inside actual implementation nothing fancy is not happening - mainly findObject method is created for loading data. Plus some getters and setters for a filtering form. The problem: dataProvider bean is kept in the request scope. But clicking any of datascroller buttons does NOT cause bean properties assigned to filter form to be filled with data from the form! When I debug this app with a breakpoint set on method loading data I see that this method is called twice - once in detached state and once not (so this object is created in request in the second time but is not filled with filtering form properties). It all boils down to a question - how can I cause datascroller to submit fully the h:form it's embedded in? Or what am I doing wroing?

      I would greatly appreciate any assistance,
      Wojtek