Spring Bootのかっこいいページネーションを考える
Spring Bootのページネーションを考えてみます。
コントローラ側の処理は省略しますが、簡単に言うとメソッドの仮引数 Pageable を定義するだけです。デフォルト値はこの仮引数にアノテーション @PageableDefault で指定します。
簡単に
ネットを見ると、大体 ${#numbers.sequence(0, page.totalPages - 1)} で作るように書いてあります。こんな感じ。ちなみにスタイルはBootstrapを使ってます。(ここで書かれている page 変数は、JPAで取得できる org.springframework.data.domain.Page インタフェースです。)
|
|
しかしこのままだと、ページが増えるとダサいことになります。

かっこよくする
よくある感じで、現在のページに近いページだけ表示したいわけですが、ネットの先輩方を尋ねるとPageインターフェースのラッパークラスを作ればいいと仰っている方もおり、「まじかよ…」という気持ちです。
身近なページネーションがあるシステムがRedmineだったんで確認してみると、「Prev」「1ページ目」「最後のページ番号」「Next」が固定で表示され、その間に現在のページと±2ページが表示されるようです。このUIはわかりやすくて好きです。

同じことをThymeleafだけで実装してみたいと思います。
。。。
はい。
少し解説します。
page.numberに現在のページ番号(0スタート)が入るので、#numbers.sequence(page.number - 2, page.number + 2)で現在のページ±2ページ分をループする。- そのままだと、マイナスになる可能性があるので(また、最大ページを超える可能性があるので)、
th:if="${i ge 0 and i lt page.totalPages}"を条件に出力する。 - 4ページ目以降(
page.number gt 2)は固定で1ページ目のリンクを表示。 - 5ページ目以降(
page.number gt 3)は固定で1ページ目の後ろに「…」を表示。 - 同じことを最後のページにも。
Viewに条件分岐を持ち込むべきじゃないとかあると思いますが、私はこの程度はViewの範疇かなと思います。これは見せ方の問題でもありますし。
その他
1ページあたりの件数を制御する
1ページあたりの件数は size パラメータを渡せば制御できます。リクエストの度にデフォルト値になってしまうため、ページ遷移のパラメータに追加してあげる必要があります。
|
|
検索条件を維持する
検索画面でのページネーションの場合は、検索条件もページ遷移のパラメータとして渡してやる必要があります。下記の例では q が検索条件です。
|
|
ソートを維持する
ソータブルな場合も、同じようにソートを sort パラメータに追加する必要がありますが、指定方法に少し癖があります。
Properties that should be sorted by in the format
property,property(,ASC|DESC). Default sort direction is ascending. Use multiplesortparameters if you want to switch directions — for example,?sort=firstname&sort=lastname,asc.
Spring Data JDBC - Reference Documentation
size と同様に ${page.sort} をそのまま渡したいところですが、この org.springframework.data.domain.Sort (と Sort.Order)は toString をオーバーライドしており フィールド名: ダイレクション という形式で出力されてしまいます。これは Pageable が期待するフォーマットではありません。このため Pageable が期待するフォーマットにシコシコ変換してやる必要があります(私が知る限り)。