photo by formalfallacy @ Dublin (Victor)
今度Scalaの書籍買ってこ。
ネットサーフィンしているとこれがいいらしい。
- 作者: Martin Odersky,Lex Spoon,Bill Venners,羽生田栄一,水島宏太,長尾高弘
- 出版社/メーカー: インプレスジャパン
- 発売日: 2011/09/27
- メディア: 単行本(ソフトカバー)
- 購入: 12人 クリック: 235回
- この商品を含むブログ (46件) を見る
Scalaをわからないまま手を動かしたせいで2日かかりました。メモします。
やりたかったこと
デザイナーからもらったhtmlソースでradioボタンがこんな感じでした。
<div class="group"> <label class="gLeft">デザイン <span class="notes nOrange">必須</span> </label> <div class="gRight"> <div class="cf"> <div class="floatBox"> <label> <input type="radio" name="design" id="design_0" value="0"> 使わない </label> </div> <div class="floatBox"> <label> <input type="radio" name="design" id="design_1" value="1"> 使う </label> </div> </div> </div> </div>
しかし、PlayFrameworkのinputRadioGroup
はこんな感じのhtmlが出力される。
@helper.inputRadioGroup(field = formValue("design"), options("0"->"使わない","1"->"使う"), 'name -> "design", '_label -> "design")
<dl class="" id="design_field"> <dt>design</dt> <dd> <span class="buttonset" id="design"> <input type="radio" id="design_0" name="design" value="0" checked="checked"/> <label for="design_0">使わない</label> <input type="radio" id="design_1" name="design" value="1" /> <label for="design_1">使う</label> </span> </dd> </dl>
これは良くない。と、いうか、ツカエナイ(°ω°
ということで、色々試してみた。
implicitで頑張る
これは教科書にも載っていたので、すぐ確認できた。もちろん時間はかかった。またimplicitは全く理解できていない。
しかし、これができたところで何も変わらなかった。正確には@helper.inputText
は問題なくできたが、@helper.inputRadioGroup
がおかしいのだ。
このソースで@helper.inputRadioGroup
を使いたい。ので、別途scalaテンプレートファイルを作成しそのファイルをimplicitして利用する形にした。
- index.scala.html
@import helper._ @inputRadioGroup(field = formValue("design"), options("0"->"使わない","1"->"使う"), 'name -> "design", '_label -> "design")(customInputRadioGroup, implicitly[Lang])
- helper/customInputRadioGroup.scala.html
@(elements: helper.FieldElements) <div class="group"> <label class="gLeft">@elements.name <span class="notes nOrange">必須</span> </label> <div class="gRight"> <div class="cf"> @elements.input </div> </div> </div>
するとですよ。。。。
<div class="group"> <label class="gLeft">design <span class="notes nOrange">必須</span> </label> <span> <span class="buttonset" id="design"> <input type="radio" id="design_0" name="design" value="0" checked="checked"> <label for="design_0">使わない</label> <input type="radio" id="design_1" name="design" value="1"> <label for="design_1">使う</label> </span> </span> </div>
じゃーん!!!!orz
このspan -> input, label
と出力される!!!この形!!!なんなの!!?
とても邪魔です。
んで、@elements.input
の中身も正規表現とか使って置換すればいいのかなと考えましたが、絶対スマートじゃないと思って、やめました。
helperを「使わない」という選択
日本のサイトからアメリカに渡米したのにもかかわらず、stackflowをさまよい続けた結果全然わからなかった。
ということで、1日あぼーんしたので、radioボタンだけhelperを使うことをやめました。
しかし、すぐに問題が起こった!!!
値が引き継がれなくなりました。(あたりまえっちゃー、当たり前ですが)
そうです。これまでForm.class
で、できることができなくなりました。自分で書かないといけなくなりました。
この時点ですごくだるくなっていました。俺がとるべき行動は次の2つありました。
- 自分で書く
- helperをカスタマイズする
ちなみにJavaもScalaも初心者レベルなので、ぜってー自分で書きたくありませんでした。勉強にはいいかもしれませんが、時間が足りない。
あきらめて、helperをどうにかしてカスタマイズすることに決定。
結局使うことに
ひとつ気がついたことがあるんです。
そもそもですよ。helperも関数(メソッド?呼び方は知らん)である。関数なんですよ。
じゃあ、オーバーライドとかもできるんじゃね? また別途似たような関数を用意しちゃえばいいんじゃね? と思いつきました!
さぁどうする?
もちろんググる。
欲しいデータはよはよ
バン はよ
バン (∩`・ω・) バン はよ
/ ミつ/ ̄ ̄ ̄/
 ̄ ̄\/___/
そして見つけました。それっぽいコードを!!!
@** * Generate an HTML radio group for Bootsrap * * Example: * {{{ * @inputRadioGroup( * contactForm("gender"), * options = Seq("M"->"Male","F"->"Female"), * '_label -> "Gender", * '_error -> contactForm("gender").error.map(_.withMessage("select gender"))) * * }}} * * @param field The form field. * @param args Set of extra HTML attributes. * @param handler The field constructor. *@ @(field: play.api.data.Field, options: Seq[(String,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) @input(field, args:_*) { (id, name, value, htmlArgs) => @options.map { v => <div class="floatBox"> <label for="@(id)_@v._1" class="radio"></label> <input type="radio" id="@(id)_@v._1" name="@name" value="@v._1" @(if(value == Some(v._1)) "checked" else "") @toHtmlArgs(htmlArgs)> @v._2 </label> </div> } }
Foooooooooooo!!!!
どうやって使えばいいのか全然わからないぜぇっ!!! orz
とりあえず、適当に使ってみる。
このファイルをこんな感じに修正しました。
- helper/bootstrapInputRadioGroup.scala.html
@(field: play.api.data.Field, options: Seq[(String,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor, lang: play.api.i18n.Lang) @input(field, args:_*) { (id, name, value, htmlArgs) => @options.map { v => <div class="floatBox"> <label> <input type="radio" id="@(id)_@v._1" name="@name" value="@v._1" @(if(value == Some(v._1)) "checked" else "") @toHtmlArgs(htmlArgs)> @v._2 </label> </div> } }
そして呼び出す箇所でこんな感じで書いてみる。
- index.scala.html
@import helper._ @bootstrapInputRadioGroup(field = formValue("design"), options("0"->"使わない","1"->"使う"), 'name -> "design", '_label -> "design")(contactFormRadio, implicitly[Lang])
- helper/customInputRadioGroup.scala.html
@(elements: helper.FieldElements) <div class="group"> <label class="gLeft">@elements.label <span class="notes nOrange">必須</span></label> <div class="gRight"> <div class="cf"> @elements.input </div> </div> </div>
するとですよ!!!!
エラーです(´;ω;`)ブワッ
[ambiguous implicit values:
both method implicitJavaLang in object PlayMagicForJava of type => play.api.i18n.Lang
and value lang of type play.api.i18n.Lang
match expected type play.api.i18n.Lang]
とりあえず全然よくわからない。調べてみてもよくわからないが、なんかScalaのバージョンが上がって、implicitするときには「play.api.i18n.Lang」はいらないよって記述っぽいのがあった!!(よくわからないので鵜呑み禁止。知っている人いましたら教えてほしい><)
というわけで削除
- helper/bootstrapInputRadioGroup.scala.html
@(field: play.api.data.Field, options: Seq[(String,String)], args: (Symbol,Any)*)(implicit handler: FieldConstructor) @input(field, args:_*) { (id, name, value, htmlArgs) => @options.map { v => <div class="floatBox"> <label> <input type="radio" id="@(id)_@v._1" name="@name" value="@v._1" @(if(value == Some(v._1)) "checked" else "") @toHtmlArgs(htmlArgs)> @v._2 </label> </div> } }
んで、エラーです(´;ω;`)ブワッ
too many arguments for method apply
でも、こんぐらいなら俺でもわかるお!(^ω^ = ^ω^)
あれでしょ。引数が多いんだよね。
implicitの箇所でimplicitly[Lang]
を削除して、引数を合わせました。
- index.scala.html
@import helper._ @bootstrapInputRadioGroup(field = formValue("design"), options("0"->"使わない","1"->"使う"), 'name -> "design", '_label -> "design")(contactFormRadio)
すると・・・・!!!
<div class="group"> <label class="gLeft">design <span class="notes nOrange">必須</span></label> <div class="gRight"> <div class="cf"> <div class="floatBox"> <label> <input type="radio" id="design_0" name="design" value="0" checked=""> 使わない </label> </div> <div class="floatBox"> <label> <input type="radio" id="design_1" name="design" value="1"> 使う </label> </div> </div> </div> </div>
でーきましたぁあああああああああああああああああああああああああ!!!!!!
よっしゃあああああああああああああああああああああああ!!!!!!
(゚∀。)ワヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャヒャ