tyoshikawa1106のブログ

- Force.com Developer Blog -

Java:Thymeleafとテンプレートレイアウトで共通化

レイアウトの共通化についてです。Spring Bootの勉強でWebアプリの開発を試していたのですが、ヘッダーやサイドメニュなど複数のページで繰り返し使用する部分が必要になりました。

f:id:tyoshikawa1106:20151203013650p:plain


Force.comならVisualforce Component、RailsならPartialがあったので、Spring Bootにも何かあるのかなと探して悩んでいたところ、この場合はThymeleafなどのテンプレートエンジンの方で検索すればいいことを教えてもらいました。


Thymeleafには日本語で翻訳されたチュートリアルサイトがあります。これをあらためて確認してみるとテンプレートレイアウトの記載が見つかりました。
f:id:tyoshikawa1106:20151203010954p:plain

Tutorial: Using Thymeleaf (ja)

インクルード可能なフラグメントを定義する

他のHTMLから呼び出す共通部品をまとめたHTMLを用意します。次のような感じです。

/templates/layout.html

f:id:tyoshikawa1106:20151203011559p:plain

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
  <body>
    <!-- Header -->
    <div th:fragment="header (title)">
      <div class="slds-media__body slds-p-top--x-small">
        <h1 class="slds-text-heading--large" th:text="${title}"></h1>
      </div>
    </div>
    <!-- SideMenu -->
    <div th:fragment="sideMenu">
      <ul class="slds-list--vertical slds-has-dividers">
        <li class="slds-list__item nav-list"><a href="/home">Home</a></li>
        <li class="slds-list__item nav-list"><a href="/account">Account</a></li>
      </ul>
    </div>
  </body>
</html>

th:fragmentで呼び出す際に使用する名称を指定するみたいです。括弧の中に変数を宣言することで引数として値をうけとれるようになります。

共通部品の呼び出し

サイドメニューの例

まずは共通部品化したサイドメニューの呼び出し例です。

/templates/home.html

f:id:tyoshikawa1106:20151203012005p:plain

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <title>Salesforce SOAP API</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link href="vendor/SLDS0120/assets/styles/salesforce-lightning-design-system.min.css" rel="stylesheet" type="text/css" />
    <link href="css/style.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <div class="slds">
      <!-- Header -->
      <header class="site-masthead slds-grid slds-page-header slds-theme--inverse commonHeader">
        <div th:include="layout :: header('Salesforce SOAP API Demo')"></div>
      </header>
      <!-- Content -->
      <div class="slds-grid slds-wrap">
        <!-- Navi -->
        <nav class="slds-col slds-size--2-of-12 sideMenu">
          <div th:include="layout :: sideMenu"></div>
        </nav>
        <!-- Main -->
        <section class="slds-col slds-size--10-of-12">
          <div class="slds-p-around--xx-large">
            <p class="slds-text-heading--large">Hello!! <span th:text="${userInfo.userFullName}"></span>!!</p>
          </div>
        </section>
      </div>
    </div>
  </body>
</html> 


『<div th:include="layout :: sideMenu"></div>』という感じでth:includeを宣言することで共通部品を呼び出せました。"layout"は呼び出す対象のHTMLファイル名です。"sideMenu"は th:fragmentの宣言で指定した名称になります。


これでth:fragment="sideMenu"の内容を呼び出すことができます。

ヘッダーの呼び出し例

続いてヘッダーの呼び出し例です。基本的には先程のサイドメニューと同じですが、こちらでは引数の値を渡してみます。

/templates/home.html

f:id:tyoshikawa1106:20151203012451p:plain

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
  <!-- ( 略 ) -->
  <body>
    <div class="slds">
      <!-- Header -->
      <header class="site-masthead slds-grid slds-page-header slds-theme--inverse commonHeader">
        <div th:include="layout :: header('Salesforce SOAP API Demo')"></div>
      </header>
      <!-- ( 略 ) -->
    </div>
  </body>
</html> 


『 th:include="layout :: header('Salesforce SOAP API Demo')"』というように括弧を宣言して渡したい値を指定します。これでlayout.htmlのheaderを呼び出し、さらに'Salesforce SOAP API Demo'という文字列をtitle変数にセットできます。


今回、ただの文字列を渡しましたが、Java側で用意した変数の値を渡したい場合は次のように宣言すればいいと思います。

${user.isAdmin}

使用例です。
f:id:tyoshikawa1106:20151203013029p:plain


また、次のように書くこともできるみたいです。この場合、順番を気にする必要がなくなるみたいです。

<div th:include="::frag (onevar=${value1},twovar=${value2})">...</div>


以上がThymeleafとテンプレートレイアウトで共通化についてです。