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" onclick="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();
         }
     }
}

你可能感兴趣的:(DAO,bean,F#,JSF,Richfaces)