By Alvin Alexander. Last updated: April 10, 2018
Just some quick notes on Play Framework (v2.3) controller form field mappings today ... I’ll add more here if/when I have time, but right now this is a reference page for my Cato CRUD Generator application.
1) The ResearchLink form from my “Finance” application:
// code from my ResearchLinks controller
// note: skipping `id` field
// note: skipping `datetime` field
val researchLinkForm: Form[ResearchLink] = Form(
mapping(
"symbol" -> nonEmptyText,
"url" -> nonEmptyText,
"notes" -> optional(text)
)
// researchLinkForm -> ResearchLink
((symbol, url, notes) => ResearchLink(0, symbol, url, Calendar.getInstance.getTime, notes))
// ResearchLink -> researchLinkForm
((rl: ResearchLink) => Some(rl.symbol, rl.url, rl.notes))
)
2) My Stock form from the same application (from the Stocks controller):
val stockForm: Form[Stock] = Form(
// defines a mapping that will handle Stock values.
// the names you use in this mapping (such as 'companyName') must match the names that will be
// POSTed to your methods in JSON.
mapping(
// verifying here creates a field-level error.
// if your test returns false, the error is shown.
"symbol" -> nonEmptyText.verifying("Doh - Stock already exists (1)!", Stock.findBySymbol(_) == 0),
"companyName" -> nonEmptyText)
((symbol, companyName) => Stock(0, symbol, companyName))
((s: Stock) => Some((s.symbol, s.companyName)))
// verifying("Doh - Stock already exists (2)!", fields => fields match {
// // this block creates a 'form' error
// // this only gets called if all field validations are okay
// case Stock(id, symbol, company) => Stock.findBySymbol(symbol) == 0
// })
)
3) My transactionForm from the same application:
val transactionForm: Form[Transaction] = Form(
// the names you use in this mapping (such as 'symbol') must match the names that will be
// POSTed to your methods in JSON.
// note: skipping `id` field
// note: skipping `datetime` field
mapping(
// verifying here creates a field-level error; if your test returns false, the error is shown
"symbol" -> nonEmptyText,
"ttype" -> nonEmptyText,
"price" -> bigDecimal,
"quantity" -> number,
"notes" -> text
)
// transactionForm -> Transaction
((symbol, ttype, price, quantity, notes) => Transaction(0, symbol, ttype, price, quantity, Calendar.getInstance.getTime, notes))
// Transaction -> TransactionForm
((t: Transaction) => Some(t.symbol, t.ttype, t.price.toDouble, t.quantity, t.notes))
)
4) A Notes form from a different application:
object Notes extends Controller with Secured {
val noteForm: Form[Note] = Form(
mapping(
"id" -> longNumber,
"title" -> text,
"note" -> text,
"sortOrder" -> longNumber
)((id, title, note, sortOrder) => Note(id, title, note, 1, currentDate, currentDate)) // from Form to Note (add process)
((note: Note) => Some(note.id, note.title, note.note, note.sortOrder)) // from Note to Form (edit process)
)
// more controller code here ...
5) And finally a Urls Play form mapping from a different application:
object Urls extends Controller with Secured {
/**
* Problems:
*
* - don't need to see 'id'
* - don't need/want to see 'user_id'
* - 'shortUrl' really can be empty
* - don't need to see 'created'
* - 'clicks' isn't needed on an input form, just output
*/
val urlForm = Form(
tuple(
"id" -> longNumber,
"url" -> nonEmptyText,
"shortUrl" -> text,
"note" -> optional(text)
)
verifying ("Short URL is already in the database", result => result match {
// TODO this works, but it could be more clear
case (id, url, shortUrl, note) => {
val uriIsAlreadyInDb = Url.uriIsInDatabase(shortUrl)
!uriIsAlreadyInDb
}
})
)
def list = IsAuthenticated { username => implicit request =>
val urls = Url.findAll()
Ok(html.urls.list(urls, urlForm))
}
def listDetails(shortUri: String) = IsAuthenticated { username => implicit request =>
val details = BrowserHeaders.findAll(shortUri)
Ok(html.urls.listUrlHits(details))
}
Other form mapping information
I’ll describe this more when I have more time, but I also have these notes on creating Play Framework form field mappings:
//--------------------------------------
// OTHER PLAY FRAMEWORK EXAMPLES & TYPES
//--------------------------------------
"date" -> optional(date("yyyy-MM-dd")), // java.util.Date
"date" -> date("yyyy-MM-dd"), // java.util.Date
"username" -> nonEmptyText,
"username" -> nonEmptyText(6), // requires a minimum of six characters
"notes" -> text,
"password" -> text(minLength = 10),
"count" -> number,
"addToMailingList" -> boolean,
"email" -> email,
"company" -> optional(text),
"numberOfShares" -> optional(number),
"stocks" -> list(text),
"emailAddresses" -> list(email),
"id" -> ignored(1234),
boolean
checked
date
email
ignored
list
longNumber
nonEmptyText
number
optional
seq
single
sqlDate
text
That’s all for today, gotta run.

