概要
ScalaのPlay Frameworkで手始めにForm処理を一つ作ってみようとしたら、ネットにあるサンプルソースから仕様が意外に変わっていたので、2.6時点での作成方法を情報整理をしてみました。
前提
ログイン画面をイメージしてFormの処理を作ってみました。気づいた点やはまった点を、ソースを交えて記載しています。
サンプルソース
【routesファイル】
GET / controllers.LoginController.loginInit
GET /login controllers.LoginController.loginInit
POST /login controllers.LoginController.loginSubmit
# Map static resources from the /public folder to the /assets URL path
GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset)
【models】
package models
case class LoginUser(
userid:String,
userpw:String);
【controllers】
package controllers
import javax.inject._
import play.api._
import play.api.mvc._
import play.api.data._
import play.api.data.Forms._
import models._
import play.api.data.validation.Valid
import play.api.data.validation.Constraint
import play.api.data.validation.Invalid
import play.api.i18n.I18nSupport
@Singleton
class LoginController @Inject()(cc: ControllerComponents) extends AbstractController(cc) with I18nSupport {
// ログインフォーム
// 空白チェックにオリジナルメッセージを設定してみる
val loginUserForm = Form( mapping("userid" -> text.verifying("ユーザIDを入力してください" , {!_.isEmpty()}) ,
"userpw" -> text.verifying("パスワードを入力してください" , {!_.isEmpty()})
)
(LoginUser.apply)(LoginUser.unapply)
)
// ログイン画面の初期表示
def loginInit() = Action { implicit request =>
Ok( views.html.login(loginUserForm) )
}
// ログイン画面のSubmit
def loginSubmit() = Action { implicit request: Request[AnyContent] =>
loginUserForm.bindFromRequest.fold(
// 入力チェックNG
errors => {
BadRequest( views.html.login(errors) )
},
// 入力チェックOK
success => {
val loginUser = loginUserForm.bindFromRequest.get
Ok( views.html.loginSuccess() )
}
)
}
}
Controllerの作成にあたってまず留意すべきことは、こちらのstackoverflowの記事より、2.6からクラスの継承に必要なものが変わった点です。
あと、これは別に2.6だからということではないのですが、空白チェックにあえてverifyingを使って試しにオリジナルのメッセージを設定してみました。また、入力チェックの詳細についてはPlayframework 2.0(Scala)でサンプルアプリケーション作成-3.メッセージの国際化(i18n)対応が参考になります。
【view】
@(loginUserForm : Form[LoginUser])(implicit request: RequestHeader, messagesProvider: MessagesProvider)
@import helper._
@main("サンプル"){
<font size=5>■ログイン画面</font><br/>
@helper.form( action = helper.CSRF(routes.LoginController.loginSubmit) ){
<fieldset>
@helper.inputText(loginUserForm("userid") , '_label -> "ログインID")
@helper.inputPassword(loginUserForm("userpw") , '_label -> "パスワード")
</fieldset>
<input type="submit" value="ログイン">
}
}
@import helper._
@main("サンプル"){
<font size=5>■ログイン成功</font>
}
まず、冒頭のimplicit parameterです。こちらのstackoverflowの記事によると、これがないと2.6ではコンパイルエラーになるそうです。
また、2.6では初期設定ではCSRFの設定がONになっているので、こちらのstackoverflowの記事によると、actionでCSRFのメソッドを使う必要があるとのこと。
また、2.6というわけではないですが、フィールドコンストラクタがviewのヘルパーの引数に設定できるので、フォームテンプレートヘルパーの利用を参考に試しに設定してみました。