Loading

ROUTE

ルートゼロの
アクティビティ

Thymeleafのth:eachでindexを取得|status変数の使い方

1

Thymeleafの`th:each`で行番号やindexを使いたいときは、反復変数の後ろに**status変数**を追加します。`th:each="user, stat : ${users}"`と書けば、`stat.index`は0始まり、`stat.count`は1始まりです。画面に「1、2、3…」と行番号を出すなら`count`、0-basedの位置が必要なら`index`を使う、と覚えると迷いません。

最初に整理:indexは0始まり、countは1始まり

プロパティ 意味 よく使う場面
stat.index 0から始まる現在位置 0-based位置が必要な処理
stat.count 1から始まる現在位置 画面の行番号・連番表示
stat.size 総要素数 現在位置 / 総件数の表示
stat.current 現在の反復要素 status側から現在要素を参照
stat.even / stat.odd 現在の反復が偶数か奇数か 交互のCSSクラスや表示条件
stat.first 最初の要素か 先頭だけ表示を変える
stat.last 最後の要素か 末尾だけ表示を変える

Thymeleaf 3.1.5の公式チュートリアルでは、status変数に`index`、`count`、`size`、`current`、`even/odd`、`first`、`last`が用意されています。status変数は反復変数の後ろへカンマ区切りで定義し、`th:each`を持つ要素とその内部で利用できます。

用語解説:status変数
th:eachの現在位置や総件数、偶奇、先頭・末尾など、繰り返し処理の状態を保持する変数です。


表に1始まりの行番号を表示する

一覧表で利用者に見せる行番号なら、0始まりの`index`より1始まりの`count`が自然です。

<table>
  <tr th:each="user, stat : ${users}">
    <td th:text="${stat.count}">1</td>
    <td th:text="${user.name}">山田</td>
  </tr>
</table>

1件目では`stat.index`が0、`stat.count`が1です。表示上の連番と0-based位置を混同しないことがポイントです。


indexを使うのは0-basedの位置が必要なとき

`index`は現在の要素が何番目かを0から数えます。0-basedの添字と対応させたい場合など、位置そのものを0始まりで扱う目的に向きます。

<ul>
  <li th:each="item, stat : ${items}">
    <span th:text="${stat.index}">0</span>
    <span th:text="${item.name}">Item</span>
  </li>
</ul>

even・oddで交互のクラスを付ける

status変数には偶数・奇数を判定する`even`と`odd`もあります。行ごとにクラスを切り替えたい場合、Controller側でフラグを作る必要はありません。

<tr th:each="user, stat : ${users}"
    th:classappend="${stat.odd} ? 'row-odd' : 'row-even'">
  <td th:text="${stat.count}">1</td>
  <td th:text="${user.name}">山田</td>
</tr>

first・lastで先頭と末尾だけ表示を変える

<div th:each="item, stat : ${items}">
  <span th:if="${stat.first}">先頭</span>
  <span th:text="${item.name}">Item</span>
  <span th:if="${stat.last}">末尾</span>
</div>

`first`と`last`は、現在の反復が最初・最後かを真偽値で返します。先頭や末尾だけ注記を出す表示に使えます。

size・currentと暗黙のStat変数

総件数は`size`、現在の反復要素は`current`です。またstatus変数を明示しない場合、Thymeleafは反復変数名の末尾へ`Stat`を付けた変数を自動作成します。`user`なら`userStat`です。

<ul>
  <li th:each="user : ${users}">
    <span th:text="${userStat.count + ' / ' + userStat.size}">1 / 3</span>
    <span th:text="${user.name}">山田</span>
  </li>
</ul>

短いテンプレートでは便利ですが、ネストした繰り返しでは明示的なstatus変数名を付けた方が追いやすくなります。

ネストしたth:eachではstatus変数名を分ける

<section th:each="category, categoryStat : ${categories}">
  <h2 th:text="${category.name}">Category</h2>
  <ul>
    <li th:each="item, itemStat : ${category.items}">
      <span th:text="${categoryStat.count}">1</span>
      <span th:text="${itemStat.count}">1</span>
      <span th:text="${item.name}">Item</span>
    </li>
  </ul>
</section>

外側と内側で`categoryStat`、`itemStat`のように別名を付けると、どちらのindex/countを参照しているか明確です。

Thymeleafの基本構文と式を一緒に確認する

`th:each`以外の基本構文もまとめて確認したい場合は、既存のThymeleaf入門記事が補助になります。

(Thymeleafの基本構文全体については『Thymeleaf入門│Spring Bootで10分実践サンプル5選』をご参照ください)

(Thymeleaf式の記号の違いについては『Thymeleafで「$」「@」「*」はどう違う?初心者でもわかる使い分け完全ガイド』をご参照ください)

よくある質問

行番号を1から表示したい場合はindex + 1でもよいですか?

表示結果としては作れますが、Thymeleafには1始まりの`count`が用意されています。単純な行番号なら`stat.count`の方が意図を直接表せます。

status変数を必ず宣言する必要がありますか?

必須ではありません。明示しない場合は反復変数名に`Stat`を付けた暗黙のstatus変数が作られます。

indexとcountは何が違いますか?

`index`は0始まり、`count`は1始まりです。0-based位置が必要ならindex、画面上の連番ならcountが分かりやすい選択です。

まとめ:表示行番号はcount、0-based位置はindex

  • `stat.index`は0始まり、`stat.count`は1始まり
  • 行番号表示ならcount、0-based位置ならindexを使う
  • size/current/even/odd/first/lastも同じstatus変数から取得できる
  • status変数を省略すると反復変数名 + Statが自動生成される
  • ネストしたループではstatus変数名を分ける

まず手元の`th:each`へ`, stat`を追加し、行番号なら`stat.count`、位置確認なら`stat.index`を表示して挙動を確かめてみてください。

カジュアル面談はこちら

RANKINGranking-icon

すべてを開示している会社です

ポジティブな面もネガティブな面も、包み隠さず誠実にお答えします。
気になることがあれば、面談の際にすべてオープンにお話します。