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

謎言語使いの徒然

適当に気になった技術や言語を流すブログ。

フォームヘルパーをタグ調整する(Play 2.3.x)

Scala Playframework

何がしたかったかと言うと、Bootstrap の形状にうまく乗せたかった。
で、試行錯誤して自分で使っててまぁ違和感がなくなったのでメモ書き

Playframework の Form については本家を参照すべし。

まず、Playframework の helper で吐き出すと、デフォルトは以下のような感じになっている。

@inputText(nameForm("name"))

すると

<dl class=" " id="name_field">
  <dt><label for="name">name</label></dt>
  <dd><input type="text" id="name" name="name" value=""></dd>
  <dd class="info">Required</dd>
</dl>

これでは bootstrap に使いづらい。

で、Playframework には helper.input なる物があり、部分的にまずは置き換えられる。

@input(field) { (id, name, value, args) =>
<input type="text" class="form-control" id="@id" name="@name" @toHtmlArgs(args) placeholder="@name" value="@value">
}

すると吐き出されるのが

<dl class=" " id="name_field">
  <dt><label for="name">name</label></dt>
  <dd><input type="text" class="form-control" id="name" name="name" placeholder="name" value=""></dd>
  <dd class="info">Required</dd>
</dl>

だがメインのタグが置き換わっただけで、ぶっちゃけそんなに意味がない。
そう、僕らが欲しいのはこっちなんだ。

<div class="form-group">
  <label for="name" class="col-sm-2 control-label">name</label>
  <div class="col-sm-10">
    <input type="text" class="form-control" id="name" name="name" placeholder="name" value="">
  </div>
  <div class="col-sm-10 col-sm-offset-2">
    <span class="help-inline">
      <span class="label label-warning">Required</span>
    </span>
  </div>
</div>

ではより少ないコーディングでそれを実現する方法はないのかというと、実はある。
views.html.helper には FieldConstructor というクラスが存在し、こいつを置き換えてやることで dl / dd なフレームを入れ替えられるようにできている。

ScalaCustomFieldConstructors

なかなかに書き方がエグいが、頑張って書いたものをそのまま上げる事にする。

まずは、FieldConstructor に読ませる為のテンプレート書く。
名前は utils/bootstrapInput.scala.html で作った

@(elements: helper.FieldElements)
<div class="form-group">
  <label for="@elements.id" class="col-sm-2 control-label">@elements.label(elements.lang)</label>
  <div class="col-sm-10">
    @elements.input
  </div>
  @if(!elements.infos.isEmpty){
  <div class="col-sm-10 col-sm-offset-2">
    <span class="help-inline">
      @for(info <- elements.infos){
      <span class="label label-warning">@info</span>
      }
    </span>
  </div>
  }

  @if(elements.hasErrors) {
  <div class="col-sm-12">
    <div class="alert alert-danger">
      <ul>
        @for(msg <- elements.errors){
        <li>@msg</li>
        }
      </ul>
    </div>
  </div>
  }
</div>

そしたら、テキストインプットを utils/formText.scala.html みたいな名前で作成

@(field: Field)
@import helper._
@implicitFieldConstructor = @{ FieldConstructor(bootstrapInput.render) }

@input(field) { (id, name, value, args) =>
    <input type="text" class="form-control" id="@id" name="@name" @toHtmlArgs(args) placeholder="@title" value="@value">
}

あとは @helper.inputText を @utils.formText に置き換えてやれば ok