テンプレート・エンジンThymeleafのチュートリアルを読む(2)
前回に引き続きテンプレート・エンジン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>
XHTMLとHTML5の特定の属性をターゲットにした同種のタグがたくさん用意されています:
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-title
とth:lang-xmllang
というこの2つのタグは、一度に同じ内容を2つの属性に設定するためのものです。詳しく言うと:
th:alt-title
はalt
とtitle
に値を設定します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:attrappend
と th: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のルールはもう少しゆるいものになっています)。そしてこれと同じことが disabled
とmultiple
、readonly
と selected
にも当てはまります。
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.