makoでrender関数を擬似的なhtmlタグとして使う
mako では、定義したrender関数を擬似的なhtmlタグのようにして使う事ができる。
(Bootstrapのdropdownのサンプル を利用)
具体的には以下の様なコードがhtmlへとレンダリングされる。
<!-- drop down widget -->
<%namespace file="./widget.html" name="w"/>
<%w:dropdown name="DropDown" id="dropdownMenu1">
<%w:menu id="first" href="#">Action</%w:menu>
<%w:menu href="#">Another Action</%w:menu>
<%w:menu href="#">Something else here</%w:menu>
<li role="presentation" class="divider"></li>
<%w:menu href="#">Separated link</%w:menu>
</%w:dropdown>
このコードが以下のようなhtmlになる(空白行を除去)。
<div class="dropdown">
<button class="btn dropdown-toggle" type="button" id=dropdownMenu1 data-toggle="dropdown">
DropDown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
<li role="presentation"><a id=first role="menuitem" tabindex="-1" href="#">Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another Action</a></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
<li role="presentation" class="divider"></li>
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
</ul>
</div>
以下詳細
makoではrender関数の呼び方が2種類ある。
以下のようなrender関数formを定義した時。
## helpers.html
<%def form="(action, method)">
<div class="form">
<form action="${action}" method="${method}">
</form>
</div>
</%def>
呼び出し方は2通りある。1つ目は${foo}形式で変数展開と同様の形で呼び出す。
<%namespace file="./helpers.html" name="h"/>
## form
${h.form(action="#", method="POST")}
また以下の様に書いても良い。これは2つ目の形式。
<%namespace file="./helpers.html" name="h"/>
## form
<%h:form action="#" method="POST"></%h:form>
タグのような形式で呼び出せる。
caller.body()を使うと、呼び出し側で内部に値を埋め込むことができる
タグのような形式で呼び出せることのの何が良いかというとコードブロックの中に何らかの値を埋め込める。
## 以下の様に書ける。
<%h:form action="#" method="POST">
<div class="field has-feedback">
<label>name:<input type="text" name="name"/></label>
</div>
</%h:form>
すると、先にラップする外側の部分を作っておき、内部の要素は呼び出し時に決めるということができる。
これを行うにはcaller.body()を使う。以下の様にコードを変更すると上の例が動作するようになる。
<%def form="(action, method)">
<div class="form">
<form action="${action}" method="${method}">
${caller.body()}
</form>
</div>
</%def>