8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Play Framework 2.6(Scala)でFormの処理を作ってみた

Last updated at Posted at 2018-08-01

概要

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】

models.scala
package models

case class LoginUser(
    userid:String, 
    userpw:String); 

【controllers】

LoginController.scala
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】

login.scala.html
@(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="ログイン">
    }
}
loginSuccess.scala.html
@import helper._
@main("サンプル"){
    <font size=5>■ログイン成功</font>
}

まず、冒頭のimplicit parameterです。こちらのstackoverflowの記事によると、これがないと2.6ではコンパイルエラーになるそうです。
また、2.6では初期設定ではCSRFの設定がONになっているので、こちらのstackoverflowの記事によると、actionでCSRFのメソッドを使う必要があるとのこと。
また、2.6というわけではないですが、フィールドコンストラクタがviewのヘルパーの引数に設定できるので、フォームテンプレートヘルパーの利用を参考に試しに設定してみました。

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?