h:datatable の ページ切り替えを考えてみた。
基本的には、以下のような Paginator になるんじゃないだろうか。
package study.jsf.pagination;
import java.util.List;
public abstract class Paginator<T> {
private final int size;
private int page = 0;
public Paginator(int size) {
this.size = size;
}
public abstract List<T> currentElements();
public abstract int itemsCount();
public int start() {
return page * size;
}
public int size() {
return size;
}
public boolean isHasNextPage() {
return (page + 1) * size() + 1 <= itemsCount();
}
public void nextPage() {
if (isHasNextPage()) page++;
}
public boolean isHasPreviousPage() {
return page > 0;
}
public void previousPage() {
if (isHasPreviousPage()) page--;
}
public int getPageSize() {
return size();
}
}
ManagedBean など、これを使う側で itemsCount()と currentElements()メソッドを実装し、型パラメータに具体型を与える。適当すぎるサンプルだが、例えば以下のように書く。
package study.jsf.pagination;
import 略
@ManagedBean(name="memberList")
@SessionScoped
public class PersonListBean {
private static final List MEMBERS_LIST = Arrays.asList(
new Person(1, "Wilhelm"),
new Person(2, "Hendrik"),
new Person(3, "Pieter"),
new Person(4, "Antoine"),
new Person(5, "Pierre"),
new Person(6, "Marie"),
new Person(7, "John"),
new Person(8, "Philipp")
);
private Paginator paginator = new Paginator(3) {
@Override
public List currentElements() {
return MEMBERS_LIST.subList(start(),
Math.min(start() + size(), itemsCount()));
}
@Override
public int itemsCount() {
return MEMBERS_LIST.size();
}
};
public Paginator getPaginator() {
return paginator;
}
public List getMembers() {
return paginator.currentElements();
}
public void next() {
paginator.nextPage();
}
public void previous() {
paginator.previousPage();
}
}
faces ファイルはこんな感じになる
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>ajax-dataTable</title>
</h:head>
<h:body>
<h:form>
<h:dataTable
id="partyTable"
value="#{memberList.members}"
var="member">
<h:column>#{member.id}</h:column>
<h:column>#{member.name}</h:column>
</h:dataTable>
<h:commandLink id="prevLink" action="#{memberList.previous}"
value="前 #{memberList.paginator.pageSize}件"
rendered="#{memberList.paginator.hasPreviousPage}">
<f:ajax execute="@this" render="@form"/>
</h:commandLink>
 
<h:commandLink
id="nextLink" action="#{memberList.next}"
value="次#{memberList.paginator.pageSize}件"
rendered="#{memberList.paginator.hasNextPage}">
<f:ajax execute="@this" render="@form"/>
</h:commandLink>
</h:form>
</h:body>
</html>
実行すると、Person オブジェクトから 3つずつ(3ページ目は2つ)がテーブルに表示され、また 3ページ目以外では「次3件」リンクが、1ページ目以外では「前3件」リンクが表示される。
あと考える事は以下のような感じか
- currentElements() は List<T>じゃなくて、DataModel<T>を返す方がいいかもしれない。
- 呼び出し側では無駄に currentElements()を呼ばずにすむような仕組みを考える必要があるかも