-
1. Re: rich:scrollableDataTable and load on demand
ilya_shaikovsky Sep 22, 2008 4:56 AM (in response to jsr34116)sorry.. your explanation isn't clear enough.. As for me I think scrollableDataTable is the component for your case - it loads data dynamixally according to scroll position.
-
2. Re: rich:scrollableDataTable and load on demand
jsr34116 Sep 22, 2008 8:47 AM (in response to jsr34116)If I use a rich:dataDable and rich:datascroller, I can get on demand page loading of the table. I.e. whenever I click next page, or specify a specific page, that page's elements are requested. This is the behavior I want, but the only problem with this approach are its looks: its not very Web 2.0.
If I use just a rich:scrollableDataTable (which is more Web 2.0), the entire table is loaded. It does not dynamically load depending upon scroll position. It always loads the entire table contents.
So the question is how does one get rich:scrollableDataTable to work as advertised? Because the provided documentation does not provide any information on how to get it to page. I've tried both the 3.21 and 3.22 GA versions with no luck. -
3. Re: rich:scrollableDataTable and load on demand
ilya_shaikovsky Sep 22, 2008 10:16 AM (in response to jsr34116)show us the code for scrollabledatatable please.
-
4. Re: rich:scrollableDataTable and load on demand
jsr34116 Sep 22, 2008 1:54 PM (in response to jsr34116)here is the .xhtml:
<a4j:form id="viewReqTableForm"> <rich:scrollableDataTable id="reqtbl" var="req" value="#{viewRequestBean.dataModel}" width="100%" sortMode="single" height="#{viewRequestBean.config.maxResultsPerPage * 25}px" columnClasses="right,left,left,left,left,right,right,left"> <rich:column width="30px"> <h:graphicImage url="images/rightArrow.png" styleClass="imgLink" title="#{msgBndl.help}"/> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="ID"/> </f:facet> <h:outputText value="#{req.requestId}"/> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Submitted By"/> </f:facet> <h:outputText value="#{req.requestor['Person-Lastname']}, #{req.requestor['Person-Firstname']}"/> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Beneficiary"/> </f:facet> <h:outputText value="#{req.beneficiary['Person-Lastname']}, #{req.beneficiary['Person-Firstname']}"/> </rich:column> <rich:column> <f:facet name="header"> <h:outputText value="Date Submitted"/> </f:facet> <h:outputText value="#{req.submitDate}"/> </rich:column> <f:facet name="footer"> <h:outputText value="#{viewRequestBean.dataModel.numRecords} Total"/> </f:facet> </rich:scrollableDataTable> </a4j:form>
Here is the DataModel bean that viewRequestBean.getDataModel returns:public class RequestList extends PagedDataModel<USSPUserRequest, Integer> { /** */ private static final long serialVersionUID = 2672142810059859813L; /** */ private int m_rowCount = -1; private String m_requestorPBWUserId; private String m_benePBWUserId; private boolean m_showAll; private DBSearch m_dbs; private String[] m_sortCols = { "REQUEST_ID", "REQUEST_ID", "REQ_LASTNAME", "PERSON_LASTNAME", "CHANGE_TYPE", "CREATE_DATE", "STATUS_ID"} ; private int m_startRow; private int m_endRow; private List<USSPUserRequest> m_requests; /** */ Logger log; public RequestList() { m_requests = null; m_startRow = -1; m_endRow = -1; m_showAll = true; m_dbs = new DBSearch( DBUtil.PRODUCT_PREFIX + "USSP_RUNTIME_V"); } public void setRequestor( String pbwuserid) { m_requestorPBWUserId = pbwuserid; } public void setBeneficiary( String pbwuserid) { m_benePBWUserId = pbwuserid; } /** * @see PaginatingDataModel#getId(java.lang.Object) */ @Override public Integer getId( USSPUserRequest object) { return new Integer( object.getId()); } /** * @see PaginatingDataModel#findObjects(int, int, java.lang.String, boolean) */ @Override public List<USSPUserRequest> findObjects( int firstRow, int numberOfRows, String sortField, boolean descending) { return getRequests( firstRow, numberOfRows, sortField, descending); } /** * @see PaginatingDataModel#getObjectById(java.lang.Object) */ @Override public USSPUserRequest getObjectById( Integer id) { return getRequest( id.intValue()); } /** * @see PaginatingDataModel#getDefaultSortField() */ @Override public String getDefaultSortField() { return "5"; // default to date submitted } /** * @see PaginatingDataModel#getNumRecords() */ @Override public int getNumRecords() { if (m_rowCount != -1) return m_rowCount; Connection conn = null; Statement stmt = null; ResultSet rs = null; Logger log = Logger.getLogger( this.getClass()); StringBuffer sql = new StringBuffer(); m_rowCount = 0; sql.append( "SELECT COUNT(*) FROM"); sql.append( " (SELECT DISTINCT REQ_BENE_REL_ID,REQUESTOR_PBWUSERID,PBWUSERID FROM "); sql.append( DBUtil.PRODUCT_PREFIX + "USSP_RUNTIME_V"); sql.append( " WHERE (REQUESTOR_PBWUSERID='"); sql.append( m_requestorPBWUserId); sql.append( "' OR PBWUSERID='"); sql.append( m_benePBWUserId); sql.append( "')"); sql.append( ")"); try { conn = DAOFactory.getDatabaseDAO().getConnection(); stmt = conn.createStatement(); log.debug( "[RequestList]:" + sql.toString()); rs = stmt.executeQuery( sql.toString()); if (rs.next()) m_rowCount = rs.getInt( 1); log.debug( "[RequestList]: count=" + m_rowCount); } catch (SQLException e) { log.debug( "[RequestList]:" + e.getLocalizedMessage(), e); } finally { DBUtils.close( conn, stmt, rs); } return m_rowCount; } public USSPUserRequest getRequest( int key) { if (m_requests == null) { System.out.println( "@@@ no search done yet!"); getRequests( 1, 20, null, true); } USSPUserRequest ret = new USSPUserRequest(); ret.setId( key); int idx = m_requests.indexOf( ret); System.out.println( "@@@ get item " + key + " idx="+idx); if (idx == -1) return null; else return m_requests.get( idx); } public List<USSPUserRequest> getRequests( int startRow, int endRow, String sortCol, boolean decending) { System.out.println( "@@@ getRequests sort col="+sortCol+" desc="+decending); if (m_requests != null && m_startRow == startRow && m_endRow == endRow) return m_requests; if (startRow == 0) startRow = 1; System.out.println( "### querying db from starting row: " + startRow); Connection conn = null; PreparedStatement ps = null; Logger log = Logger.getLogger( this.getClass()); m_requests = new ArrayList<USSPUserRequest>(); int orderBy = 0; try { orderBy = Integer.parseInt( sortCol); } catch (NumberFormatException e) { log.debug( "invalid sort column '" + sortCol + "' specified."); } if (orderBy < 0 || orderBy > m_sortCols.length) orderBy = 0; m_dbs.setOrderBy( m_sortCols[orderBy]); m_dbs.setSortDecending( decending); m_dbs.setStartIndex( startRow); m_dbs.setPageSize( endRow); m_startRow = startRow; m_endRow = endRow; try { conn = DAOFactory.getDatabaseDAO().getConnection(); ps = conn.prepareStatement( m_dbs.getQuery(), ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); USSPUserRequest builder = new USSPUserRequest(); Collection c = m_dbs.performSearch( ps, builder); m_requests.addAll( c); log.debug( "[RequestList]: found " + m_requests.size() + " requests"); System.out.println( "@@@ found " + m_requests.size() + " requests"); } catch (SQLException e) { log.debug( "[RequestList]:" + m_dbs.getQuery()); log.debug( "[RequestList]:" + e.getLocalizedMessage(), e); } finally { DBUtils.close( conn, ps, null); } return m_requests; } public void refresh() { currentPk = null; detached = false; wrappedKeys.clear(); wrappedData.clear(); rowCount = null; m_requests = null; setPageNum( 1); } } public abstract class PagedDataModel<T, U> extends SerializableDataModel { /** */ private static final long serialVersionUID = 398527390783L; /** */ protected U currentPk; /** */ protected boolean descending = false; /** */ protected String sortField = getDefaultSortField(); /** */ protected boolean detached = false; /** */ protected List<U> wrappedKeys = new ArrayList<U>(); /** */ protected Integer rowCount; /** */ protected Map<U, T> wrappedData = new HashMap<U, T>(); private int m_rowIndex; private int m_pageNum; /** * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey() */ public Object getRowKey() { System.out.println( "@@@ in getRowKey="+currentPk); return currentPk; } /** * @see org.ajax4jsf.model.ExtendedDataModel#setRowKey(java.lang.Object) */ public void setRowKey( final Object key) { System.out.println( "@@@ in setRowKey="+key); this.currentPk = (U) key; } /** * @see org.ajax4jsf.model.SerializableDataModel#update() */ public void update() { System.out.println( "@@@ in update gsfo="+getSortFieldObject()); 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; } public boolean isDescending() { return descending; } /** * @param sortField */ public void setSortField( final String sortField) { System.out.println( "@@@ setSortField " + sortField); if (this.sortField.equals( sortField)) descending = !descending; else this.sortField = sortField; } /** * @return String */ public String getSortField() { System.out.println( "@@@ getSortField " + sortField); return sortField; } /** * @see org.ajax4jsf.model.ExtendedDataModel#getSerializableModel(org.ajax4jsf.model.Range) */ public SerializableDataModel getSerializableModel( final Range range) { System.out.println( "@@@ getSerializableModel"); if (wrappedKeys != null) { detached = true; return null; //this; } return null; } /** * @see javax.faces.model.DataModel#setRowIndex(int) */ public void setRowIndex( final int rowIndex) { System.out.println( "@@@ setRowIndex "+rowIndex); m_rowIndex = rowIndex; // throw new UnsupportedOperationException(); } /** * @see javax.faces.model.DataModel#setWrappedData(java.lang.Object) */ public void setWrappedData( final Object data) { System.out.println( "@@@ setWrappedData"+data); throw new UnsupportedOperationException(); } /** * @see javax.faces.model.DataModel#getRowIndex() */ public int getRowIndex() { System.out.println( "@@@ getRowIndex "+m_rowIndex); return m_rowIndex; // throw new UnsupportedOperationException(); } /** * @see javax.faces.model.DataModel#getWrappedData() */ public Object getWrappedData() { System.out.println( "@@@ 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) */ public void walk(final FacesContext context, final DataVisitor visitor, final Range range, final Object argument) throws IOException { System.out.println( "@@@ walk"); final int firstRow = ((SequenceRange) range).getFirstRow(); int numberOfRows = ((SequenceRange) range).getRows(); System.out.println( "@@@ firstRow="+firstRow); System.out.println( "@@@ numberOfRows="+numberOfRows); System.out.println( "@@@ detached="+detached); if (numberOfRows == 0) numberOfRows = 20; if (detached && getSortFieldObject() != null) { for (final U key : wrappedKeys) { setRowKey(key); visitor.process(context, key, argument); } } else { // if not serialized, than we request data from data provider wrappedKeys = new ArrayList<U>(); for (final T 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() */ public boolean isRowAvailable() { System.out.println( "@@@ in isRowAvailable="+currentPk); 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() */ public Object getRowData() { System.out.println( "@@@ in getRowData="+currentPk); if (currentPk == null) return null; T object = wrappedData.get( currentPk); if (object == null) { object = getObjectById( currentPk); wrappedData.put( currentPk, object); } return object; } /** * @see javax.faces.model.DataModel#getRowCount() */ public int getRowCount() { System.out.println( "@@@ getRowCount"); if (rowCount == null) rowCount = getNumRecords(); return rowCount; } public int getPageNum() { return m_pageNum; } public void setPageNum( int v) { m_pageNum = v; } /** * @param object * @return U */ public abstract U getId( T object); /** * @param firstRow * @param numberOfRows * @param sortField * @param descending * @return List<T> */ public abstract List<T> findObjects( int firstRow, int numberOfRows, String sortField, boolean descending); /** * @param id * @return T */ public abstract T getObjectById( U id); /** * @return String */ public abstract String getDefaultSortField(); /** * @return int */ public abstract int getNumRecords(); }
What I am seeing is that getRowCount() is called twice, and then a loop is entered (for all rows) where setRowIndex() is called followed by getRowData(). This returns an empty table as getRowData() is expecting the row key to be set. I can change getRowData() to work off the current row, but the real problem is that the scrollableDataTable is not paging but instead requesting all rows. Note, walk() is never called.
If I use rich:dataTable and rich:datascroller, then these classes work fine. -
5. Re: rich:scrollableDataTable and load on demand
ilya_shaikovsky Sep 23, 2008 10:09 AM (in response to jsr34116)you should add rows="someNumberOfRows" ;) to your sdt tag code and this will cause the data to be loaded as you need.
-
6. Re: rich:scrollableDataTable and load on demand
jsr34116 Sep 25, 2008 5:43 PM (in response to jsr34116)I did try it before, but it wasn't doing what I expected. I.e. I expected it to automatically calculate the height of the table based on the number of rows that are being displayed. Instead controls the number of rows that are shown. It doesn't make sense to me to specify both height and rows as you can specify fewer rows than will fit in the height which leaves a bunch of empty space or more rows than will fit in height. They should be mutually exclusive in my opinion and only control the height of the table.
Okay, retesting still yeilds no results as setRowKey() is never called as walk() is never called. The loop, however, now stops at 20 which is the number of rows I specified.
The real problem is why isn't walk() being called. -
7. Re: rich:scrollableDataTable and load on demand
konstantin.mishin Sep 26, 2008 6:20 AM (in response to jsr34116)You may try to extend ScrollableTableDataModel instead of SerializableDataModel.
-
8. Re: rich:scrollableDataTable and load on demand
harsh820 Jan 21, 2011 10:20 AM (in response to konstantin.mishin)Hi John/konstantin,
Were you able to make it work by extending ScrollableTableDataModel? I am trying to do the same. But I am not sure whether I am extending it correctly. This is the first time I am trying to use something which isn't given out-of-the-box by Richfaces, so in case it worked for you, please guide me.
Here's my DataModel class.
package com.pearson.qglobal.core.util;
import java.util.List;
import javax.persistence.EntityManager;
import org.jboss.seam.annotations.Name;
import org.richfaces.model.ScrollableTableDataModel;
import org.richfaces.model.SortOrder;
@Name(value = "qglobalDataModel")
public class QGlobalDataModel<T> extends ScrollableTableDataModel<T> {
private final EntityManager entityManager;
private final String ejbqlString;
private final Long totalRecords;
private List<T> displayedList;
@SuppressWarnings("unchecked")
public QGlobalDataModel(final EntityManager entityManager, final String ejbqlString) {
super();
this.entityManager = entityManager;
this.ejbqlString = ejbqlString;
this.totalRecords = (Long) this.entityManager.createQuery("select count(e) " + this.ejbqlString)
.getSingleResult();
this.displayedList = this.entityManager.createQuery(this.ejbqlString).setFirstResult(0).setMaxResults(10)
.getResultList();
}
@SuppressWarnings(QGlobalConstants.UNCHECKED)
@Override
public List<T> loadData(final int startRow, final int endRow, final SortOrder sortOrder) {
this.displayedList =
this.entityManager.createQuery(this.ejbqlString).setFirstResult(startRow)
.setMaxResults(endRow - startRow).getResultList();
this.setWrappedData(this.displayedList);
return this.displayedList;
}
@Override
public int getRowCount() {
return totalRecords.intValue();
}
@Override
public Object getWrappedData() {
return this;
}
@SuppressWarnings(QGlobalConstants.UNCHECKED)
@Override
public void setWrappedData(final Object arg0) {
// this.displayedList = (List<T>) arg0;
}
}
I have overridden the abstract methods in ScrollableTableDataModel, which is loadData(), and getWrappedData(). The loadData() method is never called.
Thanks,
Shriharsh
-
9. Re: rich:scrollableDataTable and load on demand
sakthivel_k2003 Jan 27, 2011 10:30 PM (in response to harsh820)Hi,
I have rich scrollable data table used in my application and it is working fine. Also when I use arrow keys to scroll the rows up and down it is working fine. But once scrolling reached to last row it wrapped to the top of the list (i.e the first row). I want to stop it in the end either it reached to last row in down arrow key or it reached to first row in the up arrow key.
Could you please let me know how to achive this.
Thanks,
Sakthi
-
10. Re: rich:scrollableDataTable and load on demand
harsh820 Jan 28, 2011 12:05 AM (in response to sakthivel_k2003)Hi Sakhi,
Even I faced the issue of wrapping to top in the list. Were you able to get DB level paging work by extending ScrollableTableDataModel?
Can you please guide me where i am wrong?
-
11. rich:scrollableDataTable and load on demand
sakthivel_k2003 Jan 28, 2011 12:17 AM (in response to harsh820)No. I am not doing paging here. The issue is changing row selection by using key bord; arrow key. Say example my data list has 18 rows which has rendered in scrollable data table. I use arrow key from my keybord to select a row up and down. If the row selection reach to the last row then if I press down arrow the first row is selected. Iwant to restrict this behaviour.
-Sakthi