Play2+Scalaでのバリデーション

Play2+Scalaのバリデーションでいろいろとハマったのでメモ

やりたかったこと

  • 一つのinput要素に複数のバリデーションとエラーメッセージを設定する
  • エラーメッセージを任意の場所に表示する


これの解決に結構時間がかかりました。
やったことと発見を以下に。
例はすべてチュートリアルのtodolistが元になっています。

@inputTextについて

本題の前に用意されているhelperのinputTextのラベルとヘルプの表示について
f:id:takashima0411:20130415210647j:plain
邪魔ではないですか?邪魔ですよね。
これを消す方法があります。

index.scala.html

@inputText(taskForm("label")) 

index.scala.html

@inputText(taskForm("label"),'_label->"",'_help->"") 

この用に書き換えることで画像のように見た目上消すことができます。
f:id:takashima0411:20130415211610j:plain

ただし生成されるソースには

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

<dd class="info"></dd>

のようにlabel要素とinfo要素が残っています。
これもいらないですよね?

これを消すためにはhelperを諦めます。
helper無しで記述する場合はこうなります。

index.scala.html

<input type="text" name="label" value="@taskForm("label").value">

重要なのはnameでformで指定した値をnameにしないと適切に処理されません。
valueは初期値としてformに何かしらの値が入っている場合用です。

するとソースは以下のようになります。

<input type="text" name="label" value="">

これですっきりしました。

エラーの表示

helperのinputTextを利用するとエラーメッセージも表示されていたわけですが、
利用しなくした場合、エラーメッセージを表示する場所がありません。
エラーメッセージを表示するには以下のようにします。

<p>
    @(taskForm.error("label") match {
      case Some(error) => error.message
      case None =>
    })
</p>

これで"label"というinput要素で問題があった場合、
エラーメッセージを任意の場所に表示させることができるようになります。
これでやりたかったことの一つは解決です。

バリデーション

一つのinput要素に対し複数のバリデーションを設定します。
まず入力を10文字以内に制限してみます。

Application.scala

val taskForm = Form(
  "label" -> nonEmptyText.verifying("10文字以内で入力してください。",{_.length <= 10 })
)

すると11文字以上入力した場合エラーになります。
f:id:takashima0411:20130415213326j:plain

続けて3文字以上でないと投稿できないようにします。
Application.scala

val taskForm = Form(
  "label" -> nonEmptyText.verifying("10文字以内で入力してください。",{_.length <= 10 })
                         .verifying("3文字以上で入力してください。",{_.length >= 3})
)

これで3文字以上でなければ投稿できなくなりました。
f:id:takashima0411:20130415213724j:plain

このようにverifyingを接続していくことで複数のバリデーションを設定出来ます。
verifyingでは正規表現を利用することもできます。
その場合、次のようになります。

Application.scala

import play.api.data.validation.Constraints._

val taskForm = Form(
  "label" -> nonEmptyText.verifying("10文字以内で入力してください。",{_.length <= 10 })
                         .verifying("3文字以上で入力してください。",{_.length >= 3})
                         .verifying(pattern("""[0-9a-zA-Z]+""".r,error="半角英数だけで入力してください。"))
)

これで半角英数字だけに制限することができます。
f:id:takashima0411:20130415214010j:plain

以上でやりたかったことは実現できました。
helperなしでのエラーの取り出し方でかなりはまってしまいました…