先ほど、Handlebars.scalaについてのエントリを書きました。
Handlebars.scalaを使ってみる
http://d.hatena.ne.jp/Kazuhira/20140920/1411200907
この続きとして、Handlerbars.scalaのHelperを試してみたいと思います。
Helpers
https://github.com/mwunsch/handlebars.scala#helpers
Handlebars.scalaでは使えないもの(Helperの数が少ない)、機能もありますが、Handlebars本家のドキュメントも参考に。
Built-In Helpers
http://handlebarsjs.com/builtin_helpers.html
Handlebars.scalaには、組み込みのHelperの説明がほぼないので、詳しくはソースを読みましょう!になりますね…。
Helperって、ブロック({{# }})との違いが最初よくわからなかったんですが、機能を追加できる仕組み(JSPでいうTaglib的な?)イメージでいいんですかねー。
if helper
{{#if }}の引数として、trueかfalseでボディが評価されるかが変わります。
val template = """|{{#if this}} |trueなら、ここが表示 |{{/if}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(true) println(result)
結果。
trueなら、ここが表示
{{#if }}に渡した値がfalseならボディは評価されませんが、elseでfalse時に評価される場合の定義をすることができます。
val template = """|{{#if this}} |trueなら、ここが表示 |{{else}} |falseなら、ここが表示 |{{/if}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(false) println(result)
結果。
falseなら、ここが表示
…こう見ると、{{# }}とほぼ変わりませんけど。
each helper
コレクションなどの繰り返し用のHelperです。
val template = """|People |{{#each people}} | Person | name = {{name}} | age = {{age}} |{{/each}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(Map("people" -> List(Person("フグ田サザエ", 24), Person("磯野カツオ", 11), Person("磯野ワカメ", 9)))) println(result)
IterableやMapを反復処理することができます。
結果。
People Person name = フグ田サザエ age = 24 Person name = 磯野カツオ age = 11 Person name = 磯野ワカメ age = 9
本家と違って、elseは動かないみたいです…。
each helperでは、@indexという表記が使え、現在のインデックスを取得できます。
val template = """|People |{{#each people}} | Person:{{@index}} | name = {{name}} | age = {{age}} |{{/each}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(Map("people" -> List(Person("フグ田サザエ", 24), Person("磯野カツオ", 11), Person("磯野ワカメ", 9)))) println(result)
結果。
People Person:0 name = フグ田サザエ age = 24 Person:1 name = 磯野カツオ age = 11 Person:2 name = 磯野ワカメ age = 9
評価したものがMapだった場合は、@keyも使用できるようになります。
val template = """|Map |{{#each map}} | {{@key}}:{{this}}:{{@index}} |{{/each}} | |Map[key1] => {{map.key1}} or {{map/key1}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(Map("map" -> Map("key1" -> "value1", "key2" -> "value3", "key3" -> "value3"))) println(result)
ちなみに、Mapの値も{{Map名.キー}}や{{Map名/キー}}で取得できます。
結果。
Map key1:value1:0 key2:value3:1 key3:value3:2 Map[key1] => value1 or value1
with helper
スコープをその変数にして、ひとつ参照階層を下げることができます。
val template = """|{{#with person}} | Person | name = {{name}} | age = {{age}} |{{/with}}""".stripMargin val handlebars = Handlebars(template) val result = handlebars(Map("person" -> Person("磯野カツオ", 11))) println(result)
eachや{{# }}と迷いますが、JavaScriptのwithみたいな感じ?
結果。
Person name = 磯野カツオ age = 11
Helperを自作する
最後に、自分でHelperを作ってみましょう。
与えられた引数に「Hello」と「!」を付けて返す、簡単なものを作成してみます。
*すごいいい加減ですが…
import com.gilt.handlebars.scala.helper.{Helper, HelperOptions} import com.gilt.handlebars.scala.binding.{Binding, BindingFactory} class MyHelper[T] extends Helper[T] { override def apply(binding: Binding[T], options: HelperOptions[T])(implicit contextFactory: BindingFactory[T]): String = { val arg = options.argument(0).getOrElse("MyHelper".asInstanceOf[T]) s"Hello $arg!" } }
Helperは、まずHelperトレイトを継承して、applyメソッドをオーバーライドして定義します。Helperへの引数は、HelperOptionsとして渡ってきます。
ここでは、第1引数、なければ「MyHelper」をデフォルト値として「Hello」「!」をくっつけて返します。
applyメソッドの戻り値はStringである必要があります。
使ってみます。
val template = "{{#my word}}{{/my}}".stripMargin val handlebars = Handlebars(template) val result = handlebars(Map("word" -> "Handlebars.scala"), helpers = Map("my" -> new MyHelper)) println(result)
Handlebars#applyメソッドのhelpers引数に、自分で作ったHelperをMapとして渡します。
結果。
Hello Handlebars.scala!
ひとまず、こんなところでしょうか。