0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ページ番号が省略されるようなページング実装方法(Thymeleaf)

Last updated at Posted at 2021-03-08

1 はじめに

Spring+Thymeleafでのページング処理方法を調べてみると、下記のようなページングの実装例は簡単に見つかる。
oldPaging.png
このページングの実装は、下記の記事を参考にさせていただいた。
Spring Boot + Thymeleafでページング機能を実装する

しかし、この実装の内容だとページ数が増えた場合に横にページ番号を増やし続けてしまう。
(自分でカスタマイズしろ!というお話なのだが・・・)

そこで、次のようなページ番号が増えた場合には「...」で省略するページングを実装してみたので共有する。
(JavaScriptを使用してのページングを実装する方法もあるそうなのだが、今回はThymeleafのみで実装した。)
newPaging1.png

2 実装例

Thymeleafのコーディング例はこちら

pagination.html
<ul class="center padding-l-0">
		<li th:class="inline">
			<span th:if="${page.first}">&lt;</span>
			<a th:if="${not page.first}" th:href="@{${url}(page=${page.number-1})}">&lt;</a>
		</li>
		<!--/* 全ページ数が9以下の時は、全ページ番号を表示 */-->
		<li th:if="${page.totalPages <= 9}" th:each='i : ${#numbers.sequence(0, page.totalPages-1)}' th:class="inline">
			<span th:if='${i}==${page.number}' th:text='${i+1}'></span>
			<a th:if='${i}!=${page.number}' th:href="@{${url}(page=${i})}">
				<span th:text='${i+1}'></span>
			</a>
		</li>
		<!--/* 全ページが9以上の時 */-->
		<!--/* 1~5ページの時は後ろに「...」をつける */-->
		<li th:if="${page.totalPages > 9 && page.number < 5}" th:each='i : ${#numbers.sequence(0, 8)}' th:class="inline">
			<span th:if='${i}==${page.number}' th:text='${i+1}'></span>
			<a th:if='${i}!=${page.number}' th:href="@{${url}(page=${i})}">
				<span th:text='${i+1}'></span>
			</a>
		</li>
		<li th:if="${page.totalPages > 9 && page.number < 5}" class="inline">
			<span th:text="..."></span>
		</li>
		<!--/* (6~TotalPage数-5)ページの時は前後に「...」をつける */-->
		<li th:if="${page.totalPages > 9 && 4 < page.number && page.number < page.totalPages - 5}" class="inline">
			<span th:text="..."></span>
		</li>
		<li th:if="${page.totalPages > 9 && 4 < page.number && page.number < page.totalPages - 5}" th:each='i : ${#numbers.sequence(page.number-4, page.number+4)}' th:class="inline">
			<span th:if='${i}==${page.number}' th:text='${i+1}'></span>
			<a th:if='${i}!=${page.number}' th:href="@{${url}(page=${i})}">
				<span th:text='${i+1}'></span>
			</a>
		</li>
		<li th:if="${page.totalPages > 9 && 4 < page.number && page.number < page.totalPages - 5}" class="inline">
			<span th:text="..."></span>
		</li>
		<!--/* (TotalPage数-5)以上ページの時は前方に「...」をつける */-->
		<li th:if="${page.totalPages > 9 && page.number >= page.totalPages-5}" class="inline">
			<span th:text="..."></span>
		</li>
		<li th:if="${page.totalPages > 9 && page.number >= page.totalPages-5}" th:each='i : ${#numbers.sequence(page.totalPages-9, page.totalPages-1)}' th:class="inline">
			<span th:if='${i}==${page.number}' th:text='${i+1}'></span>
			<a th:if='${i}!=${page.number}' th:href="@{${url}(page=${i})}">
				<span th:text='${i+1}'></span>
			</a>
		</li>
		<li th:class="inline">
			<span th:if="${page.last}">&gt;</span>
			<a th:if="${not page.last}" th:href="@{${url}(page=${page.number+1})}">&gt;</a>
		</li>
	</ul>

コード中のpageオブジェクトに検索結果が格納されている。
(pageオブジェクトに検索結果を渡す処理(ControllerやServiceなど)のコーディング例は参考情報として文末に記載しておく)

条件分岐について

全ページ数(page.totalPages)や現在閲覧しているページ番号(page.number)などを使用して、下記4パターンにif条件で分岐させている。
ここでは説明のために、全ページ数をN、現在閲覧しているページ番号をxと表記することにする。

パターン1(どのページ番号も省略しない)

oldPaging.png
このパターンはN<=9の時に発生する。

パターン2(後方に...がつく)

newPaging1.png
このパターンはN>9 かつ 1<=x<=5の時に発生する。

パターン3(前方、後方に...がつく)

スクリーンショット 2021-03-08 19.07.19.png
このパターンはN>9 かつ 6<=x<=N-5の時に発生する。

パターン4(前方に...がつく)

スクリーンショット 2021-03-08 19.07.38.png
このパターンはN>9 かつ N-5<xの時に発生する。


上記のような分岐になっている。
ここでは上記のような条件分岐をさせているために、ページ番号として表示されるのは最大9件までとなっており、現在閲覧しているページから最大前後4ページまでが表示されるようになっている。
(つまり、8ページ目を閲覧している時には4~12のページ番号が表示される)
なので、表示させるページ数を増やしたい場合は上記の条件分岐に手を加えていただければ実装可能となっている。

また、このような分岐以外にも条件分岐をさせている。
例えば、現在見ているページ(page.number)のページ番号を表示する時にはaタグではなくspanタグで表記するような条件を記載している。
また、同様に次ページ前ページボタン(<,>)についても現在見ているページ(page.number)が最初のページ(page.firstがtrue)もしくは最後のページ(page.lastがtrue)ならaタグではなくてspanタグで表記するような条件としている。

参考情報(Controller、Service、Repositoryの実装例)

Controller

ItemSearchController.java
@Controller
public class ItemSearchController {

	// アイテム検索サービス
	@Autowired
	private ItemSearchService itemSearchService;

	@RequestMapping(value = "/")
	public ModelAndView searchAllItem(ModelAndView modelAndView, Pageable pageable) {
		// 全アイテムの検索
		Page<Item> itemListPage = itemSearchService.searchAllItem(pageable);

		// htmlに値を渡す
		modelAndView.addObject("page", itemListPage);
		modelAndView.addObject("itemList", itemListPage.getContent());
		modelAndView.addObject("url", "/");

		// 遷移先:アイテム検索ページ
		modelAndView.setViewName("item_search");

		return modelAndView;
	}
}

Service

ItemSearchService.java
@Service
public class ItemSearchService {

	// アイテムリポジトリ
	@Autowired
	private ItemRepository itemRepository;

	/**
	 * 全アイテム検索メソッド
	 * @return 全アイテムリスト
	 */
	public Page<Team> searchAllItem(Pageable pageable) {
		// 全チームを検索する
		return itemRepository.findAllItem(pageable);
	}
}

Repository

ItemRepository.java
@Repository
public interface ItemRepository extends JpaRepository<Item, Integer> {

	// アイテムを検索する
	@Query(value = "SELECT * FROM item", nativeQuery = true)
	public Page<Item> findAllItem(Pageable pageable);
}
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?