# Play2 Scala: Forms and Validations

Last updated:

Some reminders on how to define and use forms on Play Framework 2.x (using Scala).

HTML Forms are not discussed here. In other words, here you will find the code you might need in a controller, not in a view.

### Standalone form with tuples

import play.api.data._
import play.api.data.Forms._

val form = Form(
tuple(
"firstname" -> text,
"lastname" -> text,
"age" -> optional(number)))

//using your form in a controller action
def myAction = Action {
implicit request =>

//you can bind request params to your form
val formWData = form.bindFromRequest

if (formWData.hasErrors) {
} else {
//process params
}
}


HEADS-UP If your form has one single attribute, use single instead of tuple.

### Case-class-based Form

Say you want to define a login form for your web app; you could also define a Case class and use it and the model for your form.

The advantage of using case classes instead of simple standalone forms as above (which are based upon tuples) is that you can add methods to this class and also use it for pattern matching.

You can also use fold() to achieve this effect somewhat more elegantly: validating form in an Action

import play.api.mvc
import play.api.data._
import play.api.data.Forms._
import play.api.data.format.Formats._

//now ithe controller code:
object MyController extends BaseController{

mapping(
"rememberMe" -> default(boolean, false),
"token" -> optional(text) )(Identity.apply)(Identity.unapply))

// a controller action for the login
def login() = Action { implicit request =>

//the form data is extracted form the HTTP request

if (formWData.hasErrors)
else
Ok("Correct request") //must now check username and password to see if they match!
}
}


### Other builtin validators

• Default values
  "rememberMe" -> default(boolean,false)

• Minimum/maximum length for text
  "username" -> text(minLength=3),
"otherField" -> text(maxLength=30),
"yetAnotherField" -> text(minLength=10,maxLength=40)


### Custom validator

You can also define a custom validator for your fields - it needs to be a function that takes an attribute value and returns a Boolean.

For example, you might want to define a timeStep parameter which should only accept strings that can be seen as time steps, such as "1d" (1 hour), "10m" (for 10 minutes) and so on.

Custom validators can be defined on a per-attribute or a per-form basis (for validations that require more than one attribute to be evaluated)

val form = Form(
tuple(
"from" -> date("yyyy-MM-dd"),
"to" -> date("yyyy-MM-dd"),
//the error message is optional
"timeStep" -> text.verifying("Invalid pattern found", { txt =>
val pattern = """\d+[mhdwm]{1}"""
txt.matches(pattern)
})))


In order to validate that the date stored in to is larger than the date in from, you would have to define a validator for the whole form instead:

val form = Form(
tuple(
"from" -> date("yyyy-MM-dd"),
"to" -> date("yyyy-MM-dd"),
"timeStep" -> text)
verifying("Ending date cannot be earlier than the starting date", fields => fields match{
case data => data._1 < data._2 // lexicographic order
}
))


REFERENCES