RichFaces中利用DataTable和dataScroller

javax.servlet.ServletException: class org.richfaces.component.html.HtmlDatascroller (id="j_id_jsp_1731599958_11pc5") did not find parent form.
 javax.faces.webapp.FacesServlet.service(FacesServlet.java:249)

上面異常的原因是:datatable 和 dataScrollor一定要包含在form中

RichFaces中利用DataTable和dataScroller(基於request頁不是session啊)完美分頁解決方案

   目前實現的最爲優雅的方法,也就是不對dataTabledataScrollor做任何修改,僅僅通過擴展DataModel來實現分頁。

    DataModel是一個抽象類,用於封裝各種類型的數據源和數據對象的訪問,JSFdataTable中綁定的數據實際上被包裝成了一個DataModel,以消除各種不同數據源和數據類型的複雜性,我們訪問數據庫並拿到了一個List,交給dataTable,這時候,JSF會將這個List包裝成ListDataModeldataTable訪問數據都是通過這個DataModel進行的,而不是直接使用List

    接下來我們要將需要的頁的數據封裝到一個DataPage中去,這個類表示了我們需要的一頁的數據,裏面包含有三個元素:datasetSizestartRow,和一個用於表示具體數據的ListdatasetSize表示了這個記錄集的總條數,查詢數據的時候,使用同樣的條件取count即可,startRow表示該頁的起始行在數據庫中所有記錄集中的位置。

共用到三個類:PageListDataModel,PageListBaseBean,DataPage

其中faces-config.xml中受管Bean配置如下:

<managed-bean>
    <managed-bean-name>test</managed-bean-name>
    <managed-bean-class>com.oa.bean.Test</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
  </managed-bean>

代碼如下:

public class DataPage {
 /** *//**
     * 將需要的頁的數據封裝到一個DataPage中去, 這個類表示了我們需要的一頁的數據,<br>
     * 裏面包含有三個元素:datasetSize,startRow,和一個用於表示具體數據的List。<br>
     * datasetSize表示了這個記錄集的總條數,查詢數據的時候,使用同樣的條件取count即可,<br>
     * startRow表示該頁的起始行在數據庫中所有記錄集中的位置
     */

    private int datasetSize;

    private int startRow;

    private List data;
    /** *//**
     *
     * @param datasetSize
     *            數據集大小
     * @param startRow
     *            起始行
     * @param data
     *            數據list
     */
    public DataPage(int datasetSize, int startRow, List data)
    {

        this.datasetSize = datasetSize;

        this.startRow = startRow;

        this.data = data;

    }
    /** *//**
     *
     * @return
     */
    public int getDatasetSize()
    {

        return datasetSize;

    }

    public int getStartRow()
    {

        return startRow;

    }

    /** *//**
     *
     * @return 已填充好的數據集
     */
    public List getData()
    {

        return data;

    }
}
public abstract class PageListBaseBean {
  /** *//**
     * 當前頁碼,跟dataSroller的page屬性綁定
     */
    protected int scrollerPage = 1;
   
    /** *//**
     * 當前頁面大小
     */
    protected int pageSize = 5;
   
    /** *//**
     * 默認數據模型,如果你有多個數據集需要分頁,請自定義PagedListDataModel和相應的getDataModel方法
     */
    protected PagedListDataModel defaultDataModel;
   
    public int getScrollerPage()
    {
        return scrollerPage;
    }

    public void setScrollerPage(int scrollerPage)
    {
        this.scrollerPage = scrollerPage;
    }
   
    public int getPageSize()
    {
        return pageSize;
    }

    public void setPageSize(int pageSize)
    {
        this.pageSize = pageSize;
    }
   
    public abstract PagedListDataModel getDefaultDataModel();

}
實現類如下:

public class Test extends PageListBaseBean {
 
 public PagedListDataModel getDefaultDataModel()
    {
   if (defaultDataModel == null ) {
            defaultDataModel = new PagedListDataModel(pageSize)
            {
                public DataPage fetchPage(int startRow, int pageSize)
                {
                  
                 // call enclosing managed bean method to fetch the data
                 
                    PrivilegeDAO dao = new PrivilegeDAO();
                    String hql = "from PrivilegeGroup  order by sort desc";               
                   System.out.println("fetchPage is calling!");
                    List list = dao.getOnePageList(hql, pageSize,startRow);
                    int i=dao.getRows("select count(*) from PrivilegeGroup");
                   
                   
                  
                    return new DataPage(i, startRow, list) ;                   
                }
            };
      
   }
        return defaultDataModel;
   
    }
 
 
}

xhtml中使用如下(注意紅色部份,要保持分頁Bea狀態):

<a4j:form>


 <h:panelGroup id="del">
<rich:dataTable id="r"
     onRowMouseOver="this.style.backgroundColor='#F1F1F1'"
     onRowMouseOut="this.style.backgroundColor='#ffffff'"
     cellpadding="0" cellspacing="0"
     width="700" border="0" var="pg" value="#{test.defaultDataModel}"
     
     rows="#{test.pageSize}">
    
     <f:facet name="header">
      <rich:columnGroup>
       <rich:column >
        <h:outputText value="id" />
       </rich:column>
       
       <rich:column >
        <h:outputText value="名稱" />
       </rich:column>
       <rich:column>
        <h:outputText value="排序" />
       </rich:column>
       <rich:column>
        <h:outputText value="操作" />
       </rich:column>

      </rich:columnGroup>
     </f:facet>
 
    
    
      <rich:column>
       <h:outputText value="#{pg.id}"></h:outputText>
       
      </rich:column>
      <rich:column>
       <h:outputText value="#{pg.name}"></h:outputText>
       
      </rich:column>
      <rich:column>
       <h:outputText value="#{pg.sort}"></h:outputText>

      </rich:column>
      <rich:column align="center">
       <a4j:commandLink  action="#{privilegeGroupBean.editPrivilegeGroup}" value="修改" immediate="true" reRender="out" ajaxSingle="true">
        <f:param name="id" value="#{pg.id}"/>
       </a4j:commandLink>|
                            <a4j:commandLink action="#{privilegeGroupBean.delPrivilegeGroup}" value="刪除" reRender="del" οnclick="if(!confirm('是否要真的刪除?此操作不可恢復')){return false;}">
        <f:param name="id" value="#{pg.id}"/>
       </a4j:commandLink>#{test.scrollerPage}
      </rich:column>
    
      
     
  
     <f:facet name="footer">
    
      <rich:columnGroup>
       
       <rich:column>
        <h:outputText value="#{report.expReport.totalMeals}"><f:convertNumber   pattern="$####.00"  /></h:outputText>
       </rich:column>
       <rich:column>
        <h:outputText value="#{report.expReport.totalHotels}"><f:convertNumber   pattern="$####.00"  /></h:outputText>
       </rich:column>
       <rich:column>
        <h:outputText value="#{report.expReport.totalTransport}"><f:convertNumber   pattern="$####.00"  /></h:outputText>
       </rich:column>
       <rich:column>
        <h:outputText value="#{report.expReport.grandTotal}"><f:convertNumber   pattern="$####.00"  /></h:outputText>
       </rich:column>
      </rich:columnGroup>
     </f:facet>
  
    </rich:dataTable>
<rich:datascroller align="left" for="r" maxPages="20"
             id="sc2"  page="#{test.scrollerPage}"/>

 </h:panelGroup>  
  <a4j:keepAlive beanName="test"/> 
  
</a4j:form>
 
 
 
  
  

 

public abstract class PagedListDataModel extends DataModel {
      int pageSize;
     int rowIndex;
     DataPage page;

     /** *//**
      * Create a datamodel that pages through the data showing the specified
      * number of rows on each page.
      */
     public PagedListDataModel(int pageSize) {
         super();
         this.pageSize = pageSize;
         this.rowIndex = -1;
         this.page = null;
     }

     /** *//**
      * Not used in this class; data is fetched via a callback to the fetchData
      * method rather than by explicitly assigning a list.
      */
     public void setWrappedData(Object o) {
         if (o instanceof DataPage) {
             this.page = (DataPage) o;
         } else {
             throw new UnsupportedOperationException(" setWrappedData ");
         }
     }

     public int getRowIndex() {
         return rowIndex;
     }

     /** *//**
      * Specify what the "current row" within the dataset is. Note that the
      * UIData component will repeatedly call this method followed by getRowData
      * to obtain the objects to render in the table.
      */
     public void setRowIndex(int index) {
         rowIndex = index;
     }

     /** *//**
      * Return the total number of rows of data available (not just the number of
      * rows in the current page!).
      */
     public int getRowCount() {
         return getPage().getDatasetSize();
     }

     /** *//**
      * Return a DataPage object; if one is not currently available then fetch
      * one. Note that this doesn't ensure that the datapage returned includes
      * the current rowIndex row; see getRowData.
      */
     private DataPage getPage() {
         if (page != null) {
             return page;
         }
         int rowIndex = getRowIndex();
         int startRow = rowIndex;
         if (rowIndex == -1) {
             // even when no row is selected, we still need a page
             // object so that we know the amount of data available.
             startRow = 0;
         } // invoke method on enclosing class
         page = fetchPage(startRow, pageSize);
         return page;
     }

     /** *//**
      * Return the object corresponding to the current rowIndex. If the DataPage
      * object currently cached doesn't include that index then fetchPage is
      * called to retrieve the appropriate page.
      */
     public Object getRowData() {
         if (rowIndex < 0) {
             throw new IllegalArgumentException(
                     " Invalid rowIndex for PagedListDataModel; not within page ");
         } // ensure page exists; if rowIndex is beyond dataset size, then
         // we should still get back a DataPage object with the dataset size
         // in it
         if (page == null) {
             page = fetchPage(rowIndex, pageSize);
         }
         int datasetSize = page.getDatasetSize();
         int startRow = page.getStartRow();
         int nRows = page.getData().size();
         int endRow = startRow + nRows;
         if (rowIndex >= datasetSize) {
             throw new IllegalArgumentException(" Invalid rowIndex ");
         }
         if (rowIndex < startRow) {
             page = fetchPage(rowIndex, pageSize);
             startRow = page.getStartRow();
         } else if (rowIndex >= endRow) {
             page = fetchPage(rowIndex, pageSize);
             startRow = page.getStartRow();
         }
         return page.getData().get(rowIndex - startRow);
     }

     public Object getWrappedData() {
         return page.getData();
     }

     /** *//**
      * Return true if the rowIndex value is currently set to a value that
      * matches some element in the dataset. Note that it may match a row that is
      * not in the currently cached DataPage; if so then when getRowData is
      * called the required DataPage will be fetched by calling fetchData.
      */
     public boolean isRowAvailable() {
         DataPage page = getPage();
         if (page == null) {
             return false;
         }
         int rowIndex = getRowIndex();
         if (rowIndex < 0) {
             return false;
         } else if (rowIndex >= page.getDatasetSize()) {
             return false;
         } else {
             return true;
         }
     }

     /** *//**
      * Method which must be implemented in cooperation with the managed bean
      * class to fetch data on demand.
      */
     public abstract DataPage fetchPage(int startRow, int pageSize);

     /** *//**
      * 進行刪除等操作後會立即改變列表項並且返回列表頁的,請調用此方法,用於刷新列表。
      */
     public void refresh() {
         if (this.page != null) {
             this.page = null;
             getPage();
         }
     }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章