16571


環境 :  
\- Playframework 2.4.2

実現したい事：

  * マルチセレクトのチェックボックスを、Play 標準の helper のように定義したい。
  * 動作仕様として下記のように使いたい

@myhelper.multipleCheckBox(c("multiSelect"), Map("first" -> "1", "second" ->
"2", "third" -> "3"))

作成したコード：

[code]

    (field: play.api.data.Field, keyValues: Map[String, String])(implicit messages: play.api.i18n.Messages)
    @helper.input(field) { (id, name, value, htmlArgs) =>
    
      @{value.toString}
      @{value.getClass.toString}
    
      @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)})){checked="true"}> @kv_i._1._1
        </label>
        }
      }
    }
    
[/code]

問題点：

  * バインドした際に、「selected」属性がつかない。

val checkBoxes = Form(single("multiSelect" -> list(longNumber)))  
val test = checkBoxes.bind(Map("multiSelect[0]" -> "2"))  
println(test.value) // Some(List(2)) が表示  
println(test("multiSelect"))  
// 下記が出力(Form には value 値があるものの、Field にはない)  
// Field(Form(play.api.data.ObjectMapping1@58b5f405,Map(multiSelect[0] ->
2),List(),Some(List(2))),multiSelect,List(),None,List(),None)

しかし、この form を画面テンプレートに送っても、value 値は「None class scala.None$」の表示。

そもそも target にバインドされた時の型が Option[List[String]] や、Option[List[Long]]
のような気がしないでもないので、target に値が入っても上記コードで出ない気はしますが、そもそも target が None のままで困っています。  
これは自分のコード上のミスなのか、仕様なのかバグなのか…それすらわからない状況なので、知っている方是非ご教授下さい。

尚、レンダリング時は、下記の様な html が吐かれていて、チェックした時にサーバでバインド→値の取得はできています。

[code]

    <div class="col-sm-10">
        None
        class scala.None$
        <label class="checkbox-inline">
            <input id="multiSelect_0" name="multiSelect[0]" type="checkbox" value="1"> first
        </label>
        <label class="checkbox-inline">
            <input id="multiSelect_1" name="multiSelect[1]" type="checkbox" value="2"> second
        </label>
        <label class="checkbox-inline">
            <input id="multiSelect_2" name="multiSelect[2]" type="checkbox" value="3"> third
        </label>
    </div>
    
[/code]


CC BY-SA 3.0
2015-09-13T13:29:16.893
16566
2015-09-13T14:51:00.937
2015-09-13T14:28:27.997
380
380
question
scala playframework
Playframework2.4 の Form で list(number) をバインドした時のフィールドコンストラクタ挙動で、value 値が取得できない。


[select.html.scala](https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/select.scala.html
"select.scala.html") の実装が参考になります。

List 値を含む Field の場合、
[Field#indexes](https://github.com/playframework/playframework/blob/master/framework/src/play/src/main/scala/views/helper/select.scala.html)
で値が定義されているインデックス一覧を得ることができます。
[Field#apply](https://www.playframework.com/documentation/2.4.x/api/scala/index.html#play.api.data.Field@apply\(key:String\):play.api.data.Field)
を使うと相対的な指定で Field が取得できます。渡されてくる Field は、今回の場合 `"multiSelect"`
のキーを含みますので、`"[0]"` などのインデックスを付与して、`"multiSelect[0]"` などの Field にアクセスします。値は
`"multiSelect[0]"` などが持つため、これを比較対象として用います。

また Map は順序を保持しないため keyValues は `Seq[(String, String)]` などのほうがよいでしょう。

次のような感じになると思います。

[code]

    @(field: play.api.data.Field, keyValues: Seq[(String, String)])(implicit messages: play.api.i18n.Messages)
    @helper.input(field) { (id, name, value, htmlArgs) =>
        @defining(field.indexes.flatMap(i => field(s"[$i]").value).toSet) { values =>
            @keyValues.zipWithIndex.map { case ((k, v), idx) =>
                <label class="checkbox-inline">
                    <input id="@{id}_@{idx}" name="@{name}[@{idx}]" type="checkbox"
                    value="@{v}" @if(values(idx.toString)){checked}> @k
                </label>
            }
        }
    }
    
[/code]


CC BY-SA 3.0
2015-09-13T14:51:00.937
16571
2015-09-13T14:51:00.937
455
16566
answer