Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SCALA-229 #1650

Merged
merged 1 commit into from
Dec 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions play-scala/play-templates/app/controllers/FormController.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package controllers

import com.google.inject.Inject
import models.{
ComplexFormCustomField,
InputFormWithConstraints,
MultipleFieldsForm,
SimpleForm
}
import play.api.i18n.I18nSupport
import play.api.libs.json.Json
import play.api.mvc.{
AbstractController,
Action,
AnyContent,
ControllerComponents
}

class FormController @Inject() (cc: ControllerComponents)
extends AbstractController(cc)
with I18nSupport {

def simpleForm: Action[AnyContent] = Action { implicit request =>
Ok(views.html.Baeldung.FormTemplate(SimpleForm.form))
}

def formPost(): Action[AnyContent] = Action { implicit request =>
val form = SimpleForm.form.bindFromRequest().get
Ok(form.toString)
}

def multipleFieldsForm: Action[AnyContent] = Action { implicit request =>
Ok(views.html.Baeldung.MultipleFieldsFormTemplate(MultipleFieldsForm.form))
}

def multipleFieldsFormPost(): Action[AnyContent] = Action {
implicit request =>
val form = MultipleFieldsForm.form.bindFromRequest().get
Ok(form.toString)
}

def formWithConstraints: Action[AnyContent] = Action { implicit request =>
Ok(
views.html.Baeldung.FormTemplateWithConstraints(
InputFormWithConstraints.form
)
)
}

def formWithConstraintsPost(): Action[AnyContent] = Action {
implicit request =>
InputFormWithConstraints.form
.bindFromRequest()
.fold(
{ formWithError =>
BadRequest(
views.html.Baeldung.FormTemplateWithConstraints(formWithError)
)
},
{ data => Ok(Json.toJson(data)) }
)
}

def simpleFormPostWithErrors(): Action[AnyContent] = Action {
implicit request =>
SimpleForm.form
.bindFromRequest()
.fold(
{ formWithError =>
BadRequest(
views.html.Baeldung.FormTemplateWithErrors(formWithError)
)
},
{ data => Ok(Json.toJson(data)) }
)
}

def complexForm: Action[AnyContent] = Action { implicit request =>
Ok(views.html.Baeldung.ComplexFormTemplate(ComplexFormCustomField.form))
}

def complexFormPostWithErrors(): Action[AnyContent] = Action {
implicit request =>
ComplexFormCustomField.form
.bindFromRequest()
.fold(
{ formWithError =>
BadRequest(views.html.Baeldung.ComplexFormTemplate(formWithError))
},
{ data => Ok(Json.toJson(data)) }
)
}

}
189 changes: 189 additions & 0 deletions play-scala/play-templates/app/models/InputForms.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package models

import models.Measure.UnitMeasurement
import play.api.data.Form
import play.api.data.Forms._
import play.api.data.validation.Constraints.minLength
import play.api.libs.json.{Json, Writes}

import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.{Date, UUID}

case class SimpleForm(i: Int, active: Boolean, msg: String)

object SimpleForm {

implicit val simpleFormWrites: Writes[SimpleForm] = Json.writes[SimpleForm]
val form: Form[SimpleForm] = Form(
mapping(
"i" -> number,
"active" -> boolean,
"msg" -> text
)(SimpleForm.apply)(SimpleForm.unapply)
)

def unapply(simpleForm: SimpleForm): Option[(Int, Boolean, String)] = {
Some((simpleForm.i, simpleForm.active, simpleForm.msg))
}

}

case class MultipleFieldsForm(
i: Int,
pwd: String,
active: Boolean,
msg: String,
date: Date,
uuid: UUID,
favMovie: String,
favDrink: String
)

object MultipleFieldsForm {

implicit val multipleFieldsFormWrites: Writes[MultipleFieldsForm] =
Json.writes[MultipleFieldsForm]
val form: Form[MultipleFieldsForm] = Form(
mapping(
"i" -> number,
"pwd" -> text,
"active" -> boolean,
"msg" -> text,
"date" -> date,
"uuid" -> uuid,
"favMovie" -> text,
"favDrink" -> text
)(MultipleFieldsForm.apply)(MultipleFieldsForm.unapply)
)

def unapply(
multipleFieldsForm: MultipleFieldsForm
): Option[(Int, String, Boolean, String, Date, UUID, String, String)] = {
Some(
(
multipleFieldsForm.i,
multipleFieldsForm.pwd,
multipleFieldsForm.active,
multipleFieldsForm.msg,
multipleFieldsForm.date,
multipleFieldsForm.uuid,
multipleFieldsForm.favMovie,
multipleFieldsForm.favDrink
)
)
}

object Movies {
val list = List(
"pulpFiction" -> "Pulp Fiction",
"inception" -> "Inception",
"theMatrix" -> "The Matrix",
"titanic" -> "Titanic"
)
}

object Drinks {
val list = List(
"vodka" -> "Vodka",
"tequila" -> "Tequila",
"whisky" -> "Whisky",
"wine" -> "Wine",
"beer" -> "Beer"
)
}

}

case class ComplexFormCustomField(
i: Int,
active: Boolean,
msg: String,
measurement: UnitMeasurement
)
object ComplexFormCustomField {

implicit val complexFormWrites: Writes[ComplexFormCustomField] =
Json.writes[ComplexFormCustomField]
val form: Form[ComplexFormCustomField] = Form(
mapping(
"i" -> number,
"active" -> boolean,
"msg" -> text,
"measurement" -> Measure.unitMeasurementMapping
)(ComplexFormCustomField.apply)(ComplexFormCustomField.unapply)
)

def unapply(
complexForm: ComplexFormCustomField
): Option[(Int, Boolean, String, UnitMeasurement)] = {
Some(
(
complexForm.i,
complexForm.active,
complexForm.msg,
complexForm.measurement
)
)
}
}

case class InputFormWithConstraints(
i: Int,
msg: String,
msgOpt: Option[String],
email: String,
birthday: Date
)
object InputFormWithConstraints {

implicit val inputFormWrites: Writes[InputFormWithConstraints] =
Json.writes[InputFormWithConstraints]
val form: Form[InputFormWithConstraints] = Form(
mapping(
"i" -> number(min = 10, max = 20),
"msg" -> text(minLength = 3, maxLength = 12),
"msgOpt" -> optional(text),
"email" -> email,
"birthday" -> date
)(InputFormWithConstraints.apply)(InputFormWithConstraints.unapply)
)

def unapply(
inputForm: InputFormWithConstraints
): Option[(Int, String, Option[String], String, Date)] = {
Some(
(
inputForm.i,
inputForm.msg,
inputForm.msgOpt,
inputForm.email,
inputForm.birthday
)
)
}
}

case class InputFormWithCustomConstraints(email: String, birthday: Date)
object InputFormWithCustomConstraints {

implicit val inputFormWrites: Writes[InputFormWithCustomConstraints] =
Json.writes[InputFormWithCustomConstraints]
val form: Form[InputFormWithCustomConstraints] = Form(
mapping(
"email" -> email.verifying(minLength(15)),
"birthday" -> date.verifying(
"Not 18 years old",
d => d.toInstant.isBefore(Instant.now().minus(18, ChronoUnit.YEARS))
)
)(InputFormWithCustomConstraints.apply)(
InputFormWithCustomConstraints.unapply
)
)

def unapply(
inputForm: InputFormWithCustomConstraints
): Option[(String, Date)] = {
Some((inputForm.email, inputForm.birthday))
}
}
49 changes: 49 additions & 0 deletions play-scala/play-templates/app/models/Measure.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package models

import play.api.data.format.{Formats, Formatter}
import play.api.data.{FormError, Forms, Mapping}
import play.api.libs.json.{Json, Writes}

object Measure {

def unitMeasurementMapping: Mapping[UnitMeasurement] =
Forms.of[UnitMeasurement]

case class UnitMeasurement(quantity: Int, unit: String)

implicit def binder: Formatter[UnitMeasurement] =
new Formatter[UnitMeasurement] {
override def bind(
key: String,
data: Map[String, String]
): Either[Seq[FormError], UnitMeasurement] = Formats.parsing(
d => UnitMeasurement.fromString(d),
"The format is (\\d*)(\\s)(\\D*)- example: \"1 pound\"",
Nil
)(key, data)

override def unbind(
key: String,
value: UnitMeasurement
): Map[String, String] = Map(key -> s"${value.quantity} ${value.unit}")
}

object UnitMeasurement {

implicit val unitMeasurementFormWrites: Writes[UnitMeasurement] =
Json.writes[UnitMeasurement]

private val pattern = "(\\d*)(\\s)(\\D*)".r

def fromString(str: String): UnitMeasurement = {
val matches = pattern.findAllIn(str)
if (matches.hasNext) {
val List(number, space, quantity) = matches.subgroups
UnitMeasurement(number.toInt, quantity)
} else {
throw new RuntimeException(s"Incorrect data: $str")
}
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import helper._

@(complexFormCustomField: Form[ComplexFormCustomField])(implicit messages: Messages)


@form(action = routes.FormController.complexFormPostWithErrors()) {
@inputText(complexFormCustomField("i"))
@inputText(complexFormCustomField("active"))
@inputText(complexFormCustomField("msg"))
@inputText(complexFormCustomField("measurement"))
<input type="submit" value="Submit">
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@import helper._

@(simpleForm: Form[SimpleForm])(implicit messages: Messages)

@form(action = routes.FormController.formPost()) {
@inputText(simpleForm("i"))
@inputText(simpleForm("active"))
@inputText(simpleForm("msg"))
<input type="submit" value="Submit">
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@import helper._

@(formWithConstraints: Form[InputFormWithConstraints])(implicit messages: Messages)


@form(action = routes.FormController.formWithConstraintsPost()) {
@inputText(formWithConstraints("i"))
@inputText(formWithConstraints("msg"))
@inputText(formWithConstraints("msgOpt"))
@inputText(formWithConstraints("email"))
@inputDate(formWithConstraints("birthday"))
<input type="submit" value="Submit">
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@import helper._

@(simpleForm: Form[SimpleForm])(implicit messages: Messages)


@form(action = routes.FormController.formPost()) {
@inputText(simpleForm("i"))
@inputText(simpleForm("active"))
@inputText(simpleForm("msg"))
<input type="submit" value="Submit">
}
Loading