You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Julien Martin <ba...@gmail.com> on 2007/08/23 10:45:26 UTC

Scrolling + sorting a datatable

Hello,

I need help in order to implement a scrolling [b]combined with a[/b] sorting
strategy for a datatable.

Here is the behaviour I need:

A user should be able to scroll a datatable in steps of [b]N[/b] records.
He/she should then be able to sort that [b]N[/b] records and not the whole
of the resultset.

My problem is that I copied and pasted code in order to implement the
sorting strategy and then copied and pasted code in order to implement the
scrolling strategy and now I have the following behavior: the user can
scroll but when he/she attempts to sort, the whole of the resultset is
sorted and records not belonging to the "page" (of N records) are displayed.

Here is the Datamodel:

[code]
package com.calyonfinancial.protide;

import com.calyonfinancial.protide.entities.Protide01p;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import javax.faces.model.DataModel;
import javax.faces.model.DataModelListener;

/**
 *
 * @author Julien Martin
 */
public class SortFilterModel extends DataModel{
    private DataModel model;
    private Row[] rows;

    public SortFilterModel() {
        this((List<Protide01p>)null);
    }
    public SortFilterModel(List<Protide01p> list){
        setWrappedData(list);
    }
    public SortFilterModel(DataModel model){
        this.model = model;
        initializeRows();
    }

    public void setRowIndex(int rowIndex) {
        if(rowIndex == -1||rowIndex>=model.getRowCount()){
            model.setRowIndex(rowIndex);
        } else{
            model.setRowIndex(rows[rowIndex].row);
        }
    }


    public int getRowCount() {
        return model.getRowCount();
    }

    public Object getRowData() {
        return model.getRowData();
    }

    public int getRowIndex() {
        return model.getRowIndex();
    }

    public Object getWrappedData() {
        return model.getWrappedData();
    }

    public boolean isRowAvailable() {
        return model.isRowAvailable();
    }

    public void setWrappedData(Object object) {
        model.setWrappedData(object);
    }

    public void addDataModelListener(DataModelListener listener){
        model.addDataModelListener(listener);
    }

    public DataModelListener[] getDataModelListeners(){
        return model.getDataModelListeners();
    }

    public void removeDataModelListener(DataModelListener listener){
        model.removeDataModelListener(listener);
    }

    private void initializeRows(){
        int rowCnt = model.getRowCount();
        if(rowCnt!=-1){
            rows = new Row[rowCnt];
            for(int i = 0; i< rowCnt; ++i){
                rows[i]= new Row(i);
            }
        }
    }

    public String sortByID(){
        Arrays.sort(rows,byID);
        return null;
    }

    public String sortByIsin(){
        Arrays.sort(rows,byISIN);
        return null;
    }

    public String sortByEquityDate(){
        Arrays.sort(rows,byEquityDate);
        return null;
    }

    private static Comparator<Row> byID = new Comparator<Row>(){
        public int compare(Row r1, Row r2){
            Protide01p p1 = (Protide01p) r1.getData();
            Protide01p p2 = (Protide01p) r2.getData();
            return new Integer(p1.getTrOrderid()).compareTo(new Integer(
p2.getTrOrderid()));
        }
    };

    private static Comparator<Row> byISIN = new Comparator<Row>(){
        public int compare(Row r1, Row r2){
            Protide01p p1 = (Protide01p) r1.getData();
            Protide01p p2 = (Protide01p) r2.getData();
            return p1.getIsin().compareTo(p2.getIsin());
        }
    };

    private static Comparator<Row> byEquityDate = new Comparator<Row>(){
        public int compare(Row r1, Row r2){
            Protide01p p1 = (Protide01p) r1.getData();
            Protide01p p2 = (Protide01p) r2.getData();
            return p1.getEquityDate().compareTo(p2.getEquityDate());
        }
    };

    private class Row{
        private int row;
        public Row(int row){
            this.row = row;
        }
        public Object getData(){
            int originalIndex = model.getRowIndex();
            model.setRowIndex(row);
            Object thisRowData = model.getRowData();
            model.setRowIndex(originalIndex);
            return thisRowData;
        }
    }
}
[/code]

The code for the managed bean is as follows:
[code]
package com.calyonfinancial.protide;

import com.calyonfinancial.protide.entities.Protide01p;
import com.calyonfinancial.protide.persistence.PopulateUtil;
import java.util.List;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import org.apache.log4j.Logger;

/**
 *
 * @author Julien Martin
 */
public class Protide01pManagedBean {

    private static Logger log = Logger.getLogger("
com.calyonfinancial.protide");
    private PopulateUtil pu = new PopulateUtil();

    private List<Protide01p> lines;
    private int lineCount;
    private int firstRowIndex;
    private int numberOfRows = 10;

    private SortFilterModel protide01pModel = null;

    public Protide01pManagedBean() {
        setLines(pu.populateLinesOfProtide01p());//todo! might not need
mutator for lines
        setLineCount(lines.size());
        protide01pModel = new SortFilterModel(new ListDataModel(lines));
    }

//    public List<Protide01p> getLines() {
//        return lines;
//    }

    public SortFilterModel getLines(){
        return protide01pModel;
    }

    public void setLines(List<Protide01p> lines) {
        this.lines = lines;
    }

    public int getLineCount() {
        return lineCount;
    }

    public void setLineCount(int lineCount) {
        this.lineCount = lineCount;
    }

    public int getFirstRowIndex() {
        return firstRowIndex;
    }

    public void setFirstRowIndex(int firstRowIndex) {
        this.firstRowIndex = firstRowIndex;
    }

    public int getNumberOfRows() {
        return numberOfRows;
    }

    public void setNumberOfRows(int numberOfRows) {
        this.numberOfRows = numberOfRows;
    }

    public String scrollNext(){
        firstRowIndex += numberOfRows;
        if (firstRowIndex >= protide01pModel.getRowCount()){
            firstRowIndex = protide01pModel.getRowCount() - numberOfRows;
            if(firstRowIndex<0){
                firstRowIndex = 0;
            }
        }
        return null;
    }

    public String scrollPrevious(){
        firstRowIndex -= numberOfRows;
        if(firstRowIndex<0){
            firstRowIndex = 0;
        }
        return null;
    }

}
[/code]


Here are the relevant snippets from my JSPs:

[code]
<h:dataTable id="protidedatatable" first="#{
Protide01pManagedBean.firstRowIndex}" rows="#{
Protide01pManagedBean.numberOfRows}" value="#{Protide01pManagedBean.lines}"
var="line" styleClass="table" headerClass="th" columnClasses="td"
rowClasses="whiteRow,greyRow" width="100%" binding="#{
ContractManagedBean.protide01p}">

...


<h:commandButton value="previous" immediate="true" action="#{
Protide01pManagedBean.scrollPrevious}"/>
<h:commandButton value="next" immediate="true" action="#{
Protide01pManagedBean.scrollNext}"/>
[/code]

I am at a loss on how to proceed in order to make it work.

Can anyone help please?

Thanks in advance,

Julien.

Re: Scrolling + sorting a datatable

Posted by Mike Kienenberger <mk...@gmail.com>.
To me it sounds like you need to change how your data model is
provided to your table.

I think the most reasonable approach is to set the backing model of
the table to only include your current scroll set, then you can use a
"standard" sorting model for your table.   So each change of the
scroll set would reset the table model to a new subset of the full
data set.

Otherwise, you have to make your Sort model aware of the current
scroll set, which sounds like a much more difficult problem.

By the way, there's a Comparator-driven BaseSortableDataModel in
MyFaces that you might find useful.   I suspect it's similar to the
sort model class you have below.

http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core/src/main/java/org/apache/myfaces/component/html/ext/BaseSortableModel.java?view=markup

http://mail-archives.apache.org/mod_mbox/myfaces-dev/200703.mbox/%3c8f985b960703300919g34407a9fh74db06397f139959@mail.gmail.com%3e

On 8/23/07, Julien Martin <ba...@gmail.com> wrote:
> Hello,
>
> I need help in order to implement a scrolling [b]combined with a[/b] sorting
> strategy for a datatable.
>
> Here is the behaviour I need:
>
> A user should be able to scroll a datatable in steps of [b]N[/b] records.
> He/she should then be able to sort that [b]N[/b] records and not the whole
> of the resultset.
>
> My problem is that I copied and pasted code in order to implement the
> sorting strategy and then copied and pasted code in order to implement the
> scrolling strategy and now I have the following behavior: the user can
> scroll but when he/she attempts to sort, the whole of the resultset is
> sorted and records not belonging to the "page" (of N records) are displayed.
>
> Here is the Datamodel:
>
> [code]
> package com.calyonfinancial.protide;
>
> import com.calyonfinancial.protide.entities.Protide01p;
> import java.util.Arrays;
> import java.util.Comparator;
> import java.util.List ;
> import javax.faces.model.DataModel;
> import javax.faces.model.DataModelListener;
>
> /**
>  *
>  * @author Julien Martin
>  */
> public class SortFilterModel extends DataModel{
>     private DataModel model;
>     private Row[] rows;
>
>     public SortFilterModel() {
>         this((List<Protide01p>)null);
>     }
>     public SortFilterModel(List<Protide01p> list){
>         setWrappedData(list);
>      }
>     public SortFilterModel(DataModel model){
>         this.model = model;
>         initializeRows();
>     }
>
>     public void setRowIndex(int rowIndex) {
>         if(rowIndex == -1||rowIndex>= model.getRowCount()){
>             model.setRowIndex(rowIndex);
>         } else{
>             model.setRowIndex(rows[rowIndex].row);
>         }
>     }
>
>
>     public int getRowCount() {
>         return model.getRowCount();
>     }
>
>     public Object getRowData() {
>         return model.getRowData();
>     }
>
>     public int getRowIndex() {
>         return model.getRowIndex();
>     }
>
>      public Object getWrappedData() {
>         return model.getWrappedData();
>     }
>
>     public boolean isRowAvailable() {
>         return model.isRowAvailable();
>     }
>
>     public void setWrappedData(Object object) {
>         model.setWrappedData(object);
>     }
>
>     public void addDataModelListener(DataModelListener
> listener){
>         model.addDataModelListener(listener);
>     }
>
>     public DataModelListener[] getDataModelListeners(){
>         return model.getDataModelListeners();
>     }
>
>     public void removeDataModelListener(DataModelListener
> listener){
>         model.removeDataModelListener(listener);
>     }
>
>     private void initializeRows(){
>         int rowCnt = model.getRowCount();
>         if(rowCnt!=-1){
>             rows = new Row[rowCnt];
>             for(int i = 0; i< rowCnt; ++i){
>                 rows[i]= new Row(i);
>             }
>          }
>     }
>
>     public String sortByID(){
>         Arrays.sort(rows,byID);
>         return null;
>     }
>
>     public String sortByIsin(){
>         Arrays.sort(rows,byISIN);
>         return null;
>     }
>
>     public String sortByEquityDate(){
>         Arrays.sort(rows,byEquityDate);
>         return null;
>     }
>
>     private static Comparator<Row> byID = new Comparator<Row>(){
>         public int compare(Row r1, Row r2){
>             Protide01p p1 = (Protide01p) r1.getData();
>             Protide01p p2 = (Protide01p) r2.getData();
>             return new Integer(p1.getTrOrderid()).compareTo(new Integer(
> p2.getTrOrderid()));
>         }
>     };
>
>     private static Comparator<Row> byISIN = new Comparator<Row>(){
>         public int compare(Row r1, Row r2){
>             Protide01p p1 = (Protide01p) r1.getData();
>             Protide01p p2 = (Protide01p) r2.getData();
>             return p1.getIsin().compareTo(p2.getIsin());
>         }
>     };
>
>     private static Comparator<Row> byEquityDate = new Comparator<Row>(){
>         public int compare(Row r1, Row r2){
>             Protide01p p1 = (Protide01p) r1.getData();
>             Protide01p p2 = (Protide01p) r2.getData();
>             return p1.getEquityDate().compareTo(p2.getEquityDate ());
>         }
>     };
>
>     private class Row{
>         private int row;
>         public Row(int row){
>             this.row = row;
>         }
>         public Object getData(){
>             int originalIndex = model.getRowIndex();
>             model.setRowIndex(row);
>             Object thisRowData = model.getRowData();
>             model.setRowIndex(originalIndex);
>             return thisRowData;
>         }
>     }
> }
> [/code]
>
> The code for the managed bean is as follows:
> [code]
> package com.calyonfinancial.protide;
>
> import com.calyonfinancial.protide.entities.Protide01p;
> import com.calyonfinancial.protide.persistence.PopulateUtil
> ;
> import java.util.List;
> import javax.faces.model.DataModel;
> import javax.faces.model.ListDataModel;
> import org.apache.log4j.Logger;
>
> /**
>  *
>  * @author Julien Martin
>  */
> public class Protide01pManagedBean {
>
>     private static Logger log =
> Logger.getLogger("com.calyonfinancial.protide");
>     private PopulateUtil pu = new PopulateUtil();
>
>     private List<Protide01p> lines;
>     private int lineCount;
>     private int firstRowIndex;
>     private int numberOfRows = 10;
>
>     private SortFilterModel protide01pModel = null;
>
>     public Protide01pManagedBean() {
>         setLines(pu.populateLinesOfProtide01p ());//todo! might not need
> mutator for lines
>         setLineCount(lines.size());
>         protide01pModel = new SortFilterModel(new ListDataModel(lines));
>     }
>
> //    public List<Protide01p> getLines() {
> //        return lines;
> //    }
>
>     public SortFilterModel getLines(){
>         return protide01pModel;
>     }
>
>     public void setLines(List<Protide01p> lines) {
>         this.lines = lines;
>     }
>
>     public int getLineCount() {
>         return lineCount;
>     }
>
>     public void setLineCount(int lineCount) {
>         this.lineCount = lineCount;
>     }
>
>     public int getFirstRowIndex() {
>         return firstRowIndex;
>     }
>
>     public void setFirstRowIndex(int firstRowIndex) {
>         this.firstRowIndex = firstRowIndex;
>     }
>
>     public int getNumberOfRows() {
>         return numberOfRows;
>     }
>
>     public void setNumberOfRows(int numberOfRows) {
>         this.numberOfRows = numberOfRows;
>     }
>
>     public String scrollNext(){
>         firstRowIndex += numberOfRows;
>         if (firstRowIndex >= protide01pModel.getRowCount()){
>             firstRowIndex = protide01pModel.getRowCount() - numberOfRows;
>             if(firstRowIndex<0){
>                 firstRowIndex = 0;
>             }
>         }
>         return null;
>     }
>
>     public String scrollPrevious(){
>         firstRowIndex -= numberOfRows;
>         if(firstRowIndex<0){
>             firstRowIndex = 0;
>         }
>         return null;
>     }
>
> }
> [/code]
>
>
> Here are the relevant snippets from my JSPs:
>
> [code]
> <h:dataTable id="protidedatatable"
> first="#{Protide01pManagedBean.firstRowIndex}"
> rows="#{Protide01pManagedBean.numberOfRows }"
> value="#{Protide01pManagedBean.lines}" var="line" styleClass="table"
> headerClass="th" columnClasses="td" rowClasses="whiteRow,greyRow"
> width="100%" binding="#{ ContractManagedBean.protide01p}">
>
> ...
>
>
> <h:commandButton value="previous" immediate="true"
> action="#{Protide01pManagedBean.scrollPrevious}"/>
> <h:commandButton value="next" immediate="true" action="#{
> Protide01pManagedBean.scrollNext}"/>
> [/code]
>
> I am at a loss on how to proceed in order to make it work.
>
> Can anyone help please?
>
> Thanks in advance,
>
> Julien.
>
>