読者です 読者をやめる 読者になる 読者になる

M12i.

学術書・マンガ・アニメ・映画の消費活動とプログラミングについて

テンプレート・エンジンThymeleafのチュートリアルを読む(2)

f:id:m12i:20141101162746p:plain

前回に引き続きテンプレート・エンジンThymeleafのチュートリアルの訳出です。今回は属性値を設定・追加するための各種方法について。

原典は"Tutorial: Using Thymeleaf"の第5章です(2014/11/1 取得)。

          * * *

5 属性値を設定する

この章では、マークアップ・タグの属性値を設定(もしくは変更)する方法について見てみましょう。思うに、この機能はタグで囲まれた内容の設定に次いで、もっとも基本的ニーズのある機能のひとつでしょう。

5.1 属性値を設定する

ところで、私たち〔訳注:バーチャルな食料雑貨店の運営者たち〕はニュースレターを発行し、Webサイトのユーザがそれを購読できるようにしたいと考えました。そしてフォームを持つテンプレート /WEB-INF/templates/subscribe.html を作成しました:

<form action="subscribe.html">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe me!" />
  </fieldset>
</form>

まあ悪くない感じですね。けれどもWebアプリケーションのテンプレートというよりは単なるXHTMLというほうが正しいでしょう。まず、フォームのaction属性はそれ自体にリンクしています。URLを置換する記述になっていません。次に、送信〔submit〕ボタンのvalue属性は英語表示です。私たちとしてはここは国際化させたいと考えています。

それではth:attr属性を追加しましょう。この属性を使うとすでに設定されているタグの属性値を変更することが可能なのです:

<form action="subscribe.html" th:attr="action=@{/subscribe}">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>
  </fieldset>
</form>

考え方はきわめて単純です:th:attr属性はある属性にある値を割り当てる式をとります。あとは対応するコントローラとメッセージ・ファイルを作成すると、テンプレート・ファイルの処理結果は以下のようになるでしょう:

<form action="/gtvg/subscribe">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="¡Suscríbeme!"/>
  </fieldset>
</form>

新しい属性値が設定されていますね。加えて、/gtvg/subscribe というURLの先頭には自動でアプリケーション・コンテキストの名前が追加されていますが、これはひとつ前の章で見てきた通りです。

でも一度に複数の属性を設定したいとしたら? XMLのルール上、1つのタグに同じ属性を2回以上使うことはできません。そこでth:attr属性はカンマ区切りで複数の式をとることができます:

<img src="../../images/gtvglogo.png" 
     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

必要なメッセージ・ファイルを用意すると、以下のように出力がなされるでしょう:

<img src="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />

5.2 特定の属性を設定する

ここまで読み進めてきあなたはこのセクションのタイトルを読んで次のようなものを想像したのではないでしょうか:

<input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>

・・・マークアップの断片として見せられるとすこしぎょっとしちゃいますよね。これでも属性値の設定という機能としては十分でしょうけれど、テンプレートをつくるときに毎回毎回こんなのを書かないといけないのだとしたら、エレガントさに欠けると言わざるをえません。

Thymeleafとしても同感です。というわけで、実際のところ th:attr はあまり使用されていません。代わりにふつう使われているのは( th:attr のようにあらゆるタグを対象とするのでなく)特定のタグ属性に対して値を設定する役割を持った th:* 系の属性です。

それでは私たちのフォームのボタンの value 属性を設定するためにThymeleaf標準語はどんな属性を提供しているのでしょうか? 答えは th:value です。ものすごくわかりやすいですね。さあ、そうするとこんな感じですね:

<input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/>

いい感じになりました。先ほどのformタグのaction属性も同じようにしてみましょう:

<form action="subscribe.html" th:action="@{/subscribe}">

前の章で見た home.html の th:href を覚えていますね? あれも同じ種類の属性なのです:

<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>

XHTMLHTML5の特定の属性をターゲットにした同種のタグがたくさん用意されています:

th:abbr th:accept th:accept-charset
th:accesskey th:action th:align
th:alt th:archive th:audio
th:autocomplete th:axis th:background
th:bgcolor th:border th:cellpadding
th:cellspacing th:challenge th:charset
th:cite th:class th:classid
th:codebase th:codetype th:cols
th:colspan th:compact th:content
th:contenteditable th:contextmenu th:data
th:datetime th:dir th:draggable
th:dropzone th:enctype th:for
th:form th:formaction th:formenctype
th:formmethod th:formtarget th:frame
th:frameborder th:headers th:height
th:high th:href th:hreflang
th:hspace th:http-equiv th:icon
th:id th:keytype th:kind
th:label th:lang th:list
th:longdesc th:low th:manifest
th:marginheight th:marginwidth th:max
th:maxlength th:media th:method
th:min th:name th:optimum
th:pattern th:placeholder th:poster
th:preload th:radiogroup th:rel
th:rev th:rows th:rowspan
th:rules th:sandbox th:scheme
th:scope th:scrolling th:size
th:sizes th:span th:spellcheck
th:src th:srclang th:standby
th:start th:step th:style
th:summary th:tabindex th:target
th:title th:type th:usemap
th:value th:valuetype th:vspace
th:width th:wrap th:xmlbase
th:xmllang th:xmlspace

5.3 一度に複数の属性を設定する

さらに特別な属性が2つあります。th:alt-titleth:lang-xmllangというこの2つのタグは、一度に同じ内容を2つの属性に設定するためのものです。詳しく言うと:

  • th:alt-titlealttitleに値を設定します
  • th:lang-xmllang lang xml:langに値を設定します

私たちのバーチャル食料雑貨店について言うと、これらの属性は次のコードを置き換える手段を提供してくれます:

<img src="../../images/gtvglogo.png"
       th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

このコードは次のコードと同義になり:

<img src="../../images/gtvglogo.png" 
      th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />

このコードはまた次のコードと同義になります:

<img src="../../images/gtvglogo.png" 
      th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" />

5.4 末尾に追加、先頭に追加

th:attr と同じようにはたらくものとして、 th:attrappendth:attrprependがあります。これらは式を評価した結果を既存の属性の末尾に追加(接尾辞)もしくは先頭に追加(接頭辞)するものです。

例えば、コンテキスト変数に、ボタンに追加したい(「設定したい」ではなく、まさに「追加したい」)CSSクラス名を保存する必要があるとします。なぜならば、どんなCSSクラスを使うべきかはユーザの事前のアクション次第で決定されるからです。これは簡単に実現できます:

<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />

変数 cssStyle "warning"と設定してこのテンプレートを処理した場合、次のような結果が得られるでしょう:

<input type="button" value="Do it!" class="btn warning" />

標準語にはさらに2つの特別な追加系属性があります: th:classappend th:styleappend は、CSSクラスもしくはスタイル指定を、既存の値を上書きすることなしに追加するのに使用します:

<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">

th:each 属性については心配無用です。これはイテレーション属性というもので、後ほどご説明します。)

5.5 固定真偽値属性

XHTML/HTML5の属性のなかには、要素〔訳注:もちろんDOM要素〕にその属性があれば特定かつ固定の値を表し、存在しなければそれ以外の値を表わす──という特殊なものが存在します。

例えば checked がこれに該当します:

<input type="checkbox" name="option1" checked="checked" /> 
<input type="checkbox" name="option2" />

checkedについて、XHTML標準に従えば"checked" 以外の値は許されていません(HTML5のルールはもう少しゆるいものになっています)。そしてこれと同じことが disabledmultiplereadonlyselected にも当てはまります。

Thymeleaf標準語でもこれらの属性の操作が可能です。それらは条件式の評価結果によって設定できます。式の結果がtrueならば属性には所定の値が設定されます。一方結果がfalseならば属性には値が設定されません〔訳注:というより属性そのものが設定されません〕:

<input type="checkbox" name="active" th:checked="${user.active}" />

標準語には以下の固定真偽値属性が存在します:

th:async th:autofocus th:autoplay
th:checked th:controls th:declare
th:default th:defer th:disabled
th:formnovalidate th:hidden th:ismap
th:loop th:multiple th:novalidate
th:nowrap th:open th:pubdate
th:readonly th:required th:reversed
th:scoped th:seamless th:selected

5.6 HTML5向けの属性と要素名のサポート

この機能を使うことで、まったく異なる構文でもって──HTML5向けの構文で、テンプレートの処理をすることができるようになります:

<table> 
    <tr data-th-each="user : ${users}"> 
        <td data-th-text="${user.login}">...</td> 
        <td data-th-text="${user.name}">...</td> 
    </tr> 
</table>

data-{prefix}-{name} 構文はHTML5においいて独自の属性を記述するための標準的な手段です。開発者は th:*という形式で名前空間を使用する必要がないのです。Thymeleafはこの構文をすべての方言で〔訳注:標準語を含むすべてのサブセットで〕自動的に使用可能にしてくれます(その属性が標準語で提供されるものでなくてもです)。

独自タグ〔訳注:属性ではなくタグです〕を設定する構文もあります:{prefix}-{name}は、W3Cのカスタム要素仕様(W3C のWebコンポーネント仕様の一部)で規定されたものです。この構文は、例えば th:block ──この要素については後述します──に使用できます(つまり th-block )。

重要:この構文は、名前空間の概念を使用した th:* という構文に加えて使用できるようになるものであり、後者に取って代わるものではありません。将来的に名前空間の構文を廃止するつもりもありません。

          * * *

原典は"Tutorial: Using Thymeleaf"の第5章です(2014/11/1 取得)。


テンプレート・エンジンThymeleafのチュートリアルを読む(1) - M12i.


テンプレート・エンジンThymeleafのチュートリアルを読む(3) - M12i.


Spring関連の訳出記事まとめ - M12i.