原文地址:http://hi.baidu.com/kyunra/blog/item/8f41a186bca7933f66096e5f.html
Tapestry Table组件提供了分页的功能, 但是以前以为它只能是一次性的吧所有元素都fetch出来,然后把这些元素交给Table去处理。错了。 其实Tapetry的Table组件太强大了, 它已经把这个问题考虑了。只fetch当前页的数据。
以前做从数据库中查找数据 然后再分页时, 都是使用For 或者 Foreach组件,然后自己写一个PageNavigation组件(用于显示第几页 有多少页),还有ColumnSort组件。 其实Table已经把这些都写好。而且每次写分页时都非常麻烦。 要注意的东西太多了。
其实Table组件的核心是这些组件(Table FormTable是由下列这些组件组合而成的)
TableView 采集Table需要的信息, Source Column etc
TableColumns 显示Table 表头的信息
TableFormRows 象For组件一样list 每行的内容(用在Form中,可以提交数据)
TableRows 象For组件一样list 每行的内容(不用在Form中)
TableValues 应该被TableRows或TableFormRows包含, 每行的值
TablePages 显示Page Navigation
TableFormPages 显示Page Navigation(在Form里)
详细信息可以结合WorkBench的Table例子看Table FormTable的源码, 应该能对Table有个比较深入的理解。
下面说说怎么让Table fetch当前页面所需的数据。不知道大家有没有注意到TableView的source属性:
source
Object[]
Collection
Iterator
IBasicTableModel
in You must provide either both source and columns parameters or the tableModel parameter The data to be displayed by the component. This parameter must be used in combination with the columns parameter. The parameter must be an array of values, a collection, an iterator, or an object implementing the IBasicTableModel interface.
我们一般都是使用Object[] Collection 和 Iterator作为table的source, 有没有注意IBasicTableModel呢? 我们先看看这个接口。
package org.apache.tapestry.contrib.table.model;
import java.util.Iterator;
/**
* A simplified version of the table model that concerns itself only with
* providing the data on the current page.
*
* @author mindbridge
* @since 3.0
*/
public interface IBasicTableModel
{
/**
* Returns the number of all records
* @return the number of all rows
**/
int getRowCount();
/**
* Returns the rows on the current page.
* @param nFirst the index of the first item to be dispayed
* @param nPageSize the number of items to be displayed
* @param objSortColumn the column to sort by or null if there is no sorting
* @param bSortOrder determines the sorting order (ascending or descending)
**/
Iterator getCurrentPageRows(int nFirst, int nPageSize, ITableColumn objSortColumn, boolean bSortOrder);
}
是不是有些清晰了呢? 两个方法, 没错就是上面javadoc上面说的那样。 我们返回一个实现了IBasicTableModel的类就能做到Fetch当前页的数据: 我做了一个小例子基本包括了Table的用法。我也是仿照WorkBench的Table的例子,但是我用的是Fetch当前页面的Locale,还写了一个自定义Column。 如下(注意加粗的部分):
TablePage.html
<html jwcid="$content$">
<body jwcid=" border@Border " subTitle="Tapestry">
<form jwcid="@Form">
<span jwcid="@contrib:CheckboxGroup">
<span jwcid="@contrib:TableView"
source="ognl:model "
columns="literal: !locale:toString(), !language:displayLanguage, !country:displayCountry,
!variant:displayVariant, !isoLanguage:ISO3Language, !isoCountry:ISO3Country, =displayNameColumn "
pageSize="ognl:7"
>
<table jwcid="@Any" element="literal:table">
<tr>
<td><input type="checkbox" jwcid="@contrib:ControlCheckbox"/></td>
<td jwcid="@contrib:TableColumns"/>
</tr>
<tr jwcid=" rows@contrib:TableRows " row="ognl:currLocale">
<td><input type="checkbox" jwcid="@contrib:ControlledCheckbox" value="ognl:checkboxSelected"/></td>
<td jwcid="@contrib:TableValues"/>
</tr>
<tr>
<td colspan="6"><span jwcid="@contrib:TablePages" pagesDisplayed="ognl:10"/></td>
<td><input type="sumit" jwcid="@Submit" listener="listener:listItems" value="List"/></td>
</tr>
</table>
</span>
</span>
</form>
<span jwcid="@If" condition="ognl:(listItems==null ||listItems.size()>0)">
<span jwcid="@For" source="ognl:listItems" value="ognl:item">
<span jwcid="@Insert" value="ognl:item"></span>
<br/>
</span>
</span>
</body>
</html>
TablePage.java
package com.dengyin.tapestry.pages;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import org.apache.tapestry.annotations.InitialValue;
import org.apache.tapestry.annotations.Meta;
import org.apache.tapestry.annotations.Persist;
import org.apache.tapestry.contrib.table.model.IBasicTableModel;
import org.apache.tapestry.contrib.table.model.ITableColumn;
import org.apache.tapestry.contrib.table.model.simple.ITableColumnEvaluator;
import org.apache.tapestry.contrib.table.model.simple.SimpleTableColumn;
import com.dengyin.tapestry.DemoBasePage;
@Meta(
{ "anonymous-access=true", "admin-page=false" })
public abstract class TablePage extends DemoBasePage {
@Persist("session")
@InitialValue("new java.util.HashSet()")
public abstract Set<Locale> getSelectedLocales();
public abstract void setSelectedLocales(Set<Locale> set);
public abstract Locale getCurrLocale();
@InitialValue("new java.util.HashSet()")
public abstract Set<Locale> getListItems();
public abstract void setListItems(Set<Locale> set);
public boolean getCheckboxSelected(){
return getSelectedLocales().contains(getCurrLocale());
}
public void setCheckboxSelected(boolean checked){
Set<Locale> selectedLocales = getSelectedLocales();
if (checked){
selectedLocales.add(getCurrLocale());
}else{
selectedLocales.remove(getCurrLocale());
}
//make persist
setSelectedLocales(selectedLocales);
}
public ITableColumn getDisplayNameColumn(){
return new SimpleTableColumn("displayName", "displayName", new ITableColumnEvaluator(){
private static final long serialVersionUID = 6228368700745851970L;
public Object getColumnValue(ITableColumn objColumn, Object objRow) {
Locale locale = (Locale) objRow;
return locale.getDisplayName();
}
}, false
);
}
public IBasicTableModel getModel(){
return new IBasicTableModel(){
public int getRowCount() {
return Locale.getAvailableLocales().length;
}
public Iterator getCurrentPageRows(int nFirst, int nPageSize, ITableColumn objSortColumn, boolean bSortOrder) {
int count = Locale.getAvailableLocales().length;
int begInIndex = nFirst; //nFirst the index of the element. not the page index
int endIndex = nFirst + nPageSize -1;
//if the last page don't contain pageSize's elements, it will throw ArrayIndexOutOfBoundsException.
// so we need to catch this.
if (endIndex > count -1){
endIndex = count -1;
}
List<Locale> result = new ArrayList<Locale>();
for(int i = begInIndex; i<=endIndex; i++ ){
result.add(Locale.getAvailableLocales()[i]);
}
return result.iterator();
}
};
}
public abstract Locale getItem();
public void listItems(){
setListItems(getSelectedLocales());
}
}