37
41

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 5 years have passed since last update.

Thymeleafのth:replaceとth:includeはこう使い分ける!

Last updated at Posted at 2016-03-19

最近SpringBoot x Thymeleafを本格的に使うようになったのですが、先日UI部品の共通化で少し混乱したことがあったのでコトの顛末をまとめておきます。

先に結論

先に結論だけ書いておきます。
共通化したいパーツが1つのタグに収まっていればth:replace、そうでなければth:includeを使う。

Thymeleafでは部品の共通化のために2つの方法が提供されています。th:replaceth:includeです。これらは上記のルールに基づいて使い分けることができます。
本家サイトにもth:includeとth:replaceの違いという項目はあり、以下のように書かれているのですが、

th:include と th:replace の違いって何でしょうか? th:include はホストタグの中にフラグメントの中身をインクルードする一方で th:replace は実際にホストタグをフラグメントで置換します。

私には初見ではよくわかりませんでした。
そこで挙動を整理してみたところ、本家の解説の意味にもシンプルなルールにも気づけました。

では順番に挙動を見ていきましょう。
以下に登場するコードはgithubにあげてあります。

th:replaceの挙動

th:replace書かれたタグをth:fragmentが書かれたタグで置き換えます。
単純にタグを置換するので、th:replaceタグとth:fragmentタグが1:1対応している必要があります。

たとえばこのような場合、th:replaceを使うことができます。

src
<div th:replace="common::replace"></div>
<hr class="ui divider">
<div th:replace="common::replace"></div>

th_replace.PNG

display
<div class="ui container">
  <div class="ui buttons">
    <button class="ui primary button">Save</button>
    <div class="or"></div>
    <button class="ui button">Cancel</button>
  </div>
</div>
<hr class="ui divider">
<div class="ui container">
  <div class="ui buttons">
    <button class="ui primary button">Save</button>
    <div class="or"></div>
    <button class="ui button">Cancel</button>
  </div>
</div>

<button>の集合がグループ化されて一つのタグにまとめられているので、th:replaceでガツンと置換してしまえばキレイに意図したViewが構築できますね。

th:includeの挙動

th:include書かれたタグはそのままに、タグの内部を書き換えます。
th:replaceと違い、共通部品と1:1対応でなくとも置換が可能です。

src
<div class="ui three item menu" th:include="common::include"></div>
<hr class="ui divider">
<div class="ui vertical menu" th:include="common::include"></div>

th_include.PNG

display
<div class="ui three item menu">
  <a class="active item" href="#">item 1</a>
  <a class="item" href="#">item 2</a>
  <a class="item" href="#">item 3</a>
</div>
<hr class="ui divider">
<div class="ui vertical menu">
  <a class="active item" href="#">item 1</a>
  <a class="item" href="#">item 2</a>
  <a class="item" href="#">item 3</a>
</div>

th:includeを書いたタグのclass指定によって、縦並びと横並びが入れ替わっています。このような指定をしたい時はth:includeが有効だといえます。

まとめ: 作れない構成もあるので気をつけて

しかし、これでは共通化部品が一つのタグにまとまっていなくて、かつ親タグが共通部品以外の子要素を持っていたら書けません。

example
<div>
    <p>共通化したい部品1</p>
    <p>共通化したい部品2</p>
    <p>共通化したい部品3</p>
    <div>このページ固有の要素たち</div>
</div>

一旦今はそのような状況に遭遇はしていませんが、そうなったらHTMLの構成で吸収するしかなさそうです。

37
41
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
37
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?