フォームヘルパーをタグ調整する(Play 2.4.x) with マルチセレクトチェックボックス
Playframework 2.4 において、フィールドコンストラクタの仕様も変わったので、対応したチェックボックスを作ってみる。
Custom Field Constructors
これがなんなのかというと、input とかの helpers の外枠の事。
いつぞや Bootstrap 対応した フォームヘルパーをタグ調整する(Play 2.3.x) - 謎言語使いの徒然 を焼き直す。
Bootstrap インストール
まずは、いろいろやるのが面倒なので、build.sbt
に下記を用意する。
libraryDependencies ++= Seq( "com.github.aselab" %% "scala-activerecord" % "0.3.1", "com.h2database" % "h2" % "1.4.185" % "test", "mysql" % "mysql-connector-java" % "5.1.34", // この下 3 行を追加 "org.webjars" %% "webjars-play" % "2.4.0-1", "org.webjars" % "jquery" % "1.11.3", "org.webjars" % "bootstrap" % "3.3.5", evolutions, jdbc, cache, ws, specs2 % Test ) // あとから書くのも面倒なので追加。 TwirlKeys.templateImports += "views.html.commons._"
そしたら、conf/routes
に下記を追記
GET /webjars/*file controllers.WebJarAssets.at(file)
app/view/main.scala.html
も Bootstrap 取り込み。
@(title: String)(content: Html) <!DOCTYPE html> <html lang="en"> <head> <title>@title</title> <link rel="stylesheet" media="screen" href="@routes.Assets.versioned("stylesheets/main.css")"> <link rel="shortcut icon" type="image/png" href="@routes.Assets.versioned("images/favicon.png")"> <!-- custom for bootstrap --> <link rel='stylesheet' href='@routes.WebJarAssets.at(WebJarAssets.locate("css/bootstrap.min.css"))'> <script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("jquery.min.js"))'></script> <script type='text/javascript' src='@routes.WebJarAssets.at(WebJarAssets.locate("js/bootstrap.min.js"))'></script> </head> <body> <!-- Wrap bootstrap container --> <div class="container-fluid">@content</div> </body> </html>
跡はTodoリストでも勝手に書いて。
ちなみに、Bootstrap の入力フォームは、各 input タグに class="form-control"
入れないとデザイン整わないので注意。
カスタムフィールドコンストラクタの作成
と言っても言うほどの事もないか?
app/views/commons/bootstrapFields.scala.html
作って、下記を置く。
@(elements: helper.FieldElements) <div class="form-group @if(elements.hasErrors){has-error}"> <label for="@elements.id" class="col-sm-2 control-label">@elements.label</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>
そして、パッケージオブジェクトを作成する。
package views.html package object commons { import views.html.helper.FieldConstructor implicit val bootStrapFieldConstructor = FieldConstructor(bootstrapFields.f) }
import 設定は、build.sbt に入れてあるので、後は普通に helpers.input とか使うだけ。
マルチセレクトチェックボックス
デフォルトのヘルパーにいないので、頑張って作ってみた。
え?頑張ってないじゃないかって?実は問題が一つあるんだけど、後で話そう。
@(field: play.api.data.Field, keyValues: Map[String, String])(implicit messages: play.api.i18n.Messages) @helper.input(field) { (id, name, value, htmlArgs) => @defining(keyValues.toList.zipWithIndex){ results => @for(kv_i <- results){ <label class="checkbox-inline"> <input id="@{id}_@{kv_i._2}" name="@{name}[@{kv_i._2}]" type="checkbox" value="@{kv_i._1._2}" @if(value.exists(v => {keyValues.exists(_._2 == v)})){selected}> @kv_i._1._1 </label> } } }
使い方的には、フォームを下記の定義にして
val checkBoxes = { import play.api.data.Forms._ Form(single("multiSelect" -> list(longNumber))) }
テンプレート上でこう
@multipleCheckBox(checkBoxes("multiSelect"), Map("first" -> "1", "second" -> "2", "third" -> "3"))
そして、問題はなんなのかというと、バインドしたフォームを指定してもチェックが付かないという事。
解決しようと 3 時間くらい粘ったけど、結局未解決。
追記。
上記リンク先で、無事解決しました。
kawty さんありがとうございます。