本文来自:http://fair-jm.iteye.com/ 转截请注明出处
许久不更新...单纯是因为懒罢了...
play.api.data.Form
Controller中使用:
创建实体:
case class User(username: String,realname: Option[String],email: String)
创建Form对象
val userForm = Form( mapping( //制定验证规则 "username" -> nonEmptyText(8), "realname" -> optional(text), "email" -> email)(User.apply)(User.unapply)) def createUser() = Action { implicit request => userForm.bindFromRequest.fold( formWithErrors => BadRequest, //有错误的情况 得到的还是一个Form 可以通过getErrors获得错误 user => Ok("User OK!")) //没有错误的情况 得到的是一个User对象 }
fold的返回值是play.api.mvc.SimpleResult 是BadRequest和Ok的祖先
表格的Mapping 做binding(绑定)和unbinding的操作
把数据放入Form中叫做绑定
Forms是不可变的 binding之后返回一个新的拷贝
一个mapping是一个Mapping[T]对象
以上的代码中 Forms.nonEmptyText 创建了一个Mapping[String] email创建了一个Mapping[String] 更多的Forms.number创建了一个Mapping[Int]
更多的:
- ■boolean: Mapping[Boolean]
- ■ checked(msg: String): Mapping[Boolean]
- ■ date: Mapping[Date]
- ■ email: Mapping[String]
- ■ ignored[A](value: A): Mapping[A]
- ■ longNumber: Mapping[Long]
- ■ nonEmptyText: Mapping[String]
- ■ number: Mapping[Int]
- ■ sqlDate: Mapping[java.sql.Date]
- ■ text: Mapping[String]
form helper:
可以手动写name和mapping中的对应就好了要获取form内的值用data属性就可以了 data是Map对象
也可以借助helper:
@(productForm: Form[Product]) @main("Product Form") { @helper.form(action = routes.GeneratedForm.create) { @helper.inputText(productForm("name")) @helper.textarea(productForm("description")) @helper.inputText(productForm("ean")) @helper.inputText(productForm("pieces")) @helper.checkbox(productForm("active")) <div class="form-actions"> <button type="submit">Create Product</button> </div> } }
会自动生成html 如果要自定义提示信息 查看一下trait Constraints Scaladoc
helper的input:
■ inputDate —Generates an input tag with type date.
■ inputPassword —Generates an input tag with type password .
■ inputFile —Generates an input tag with type file.
■ inputText —Generates an input tag with type text.
■ select —Generates a select tag.
■ inputRadioGroup —Generates a set of input tags with type radio .
■ checkbox —Generates an input tag with type checkbox .
■ textarea —Generates a textarea element.
■ input —Creates a custom input.
可以增加自定义的属性:
@helper.inputText(productForm("name"), '_class -> "important", 'size -> 40)
'size和'_class是symbol类型的
更多的属性:
■ _label —Use to set a custom label
■ _id —Use to set the id attribute of the dl element
■ _class —Use to set the class attribute of the dl element
■ _help —Use to show custom help text
■ _showConstraints —Set to false to hide the constraints on this field
■ _error —Set to a Some[FormError] instance to show a custom error
■ _showErrors —Set to false to hide the errors on this field
自定义input:
@helper.input(myForm("mydatetime")) { (id, name, value, args) => <input type="datetime" name="@name" id="@id" value="@value" @toHtmlArgs(args)> }
第二个参数接受的是一个函数 参数是(String,String,Option[String],Map[Symbol,Any])
(toHtmlArgs来自play.api.templates.PlayMagic)
生成自定义的html:
在views.helper中(也可以是其他包啦 在views下面方便一点) 建立
myFileConstructor.scala.html
写入自定义html:
@(elements: helper.FieldElements) <div id="@(elements.id)_field" class="clearfix @if(elements.hasErrors) {text-error}"> <label for="name">@elements.label</label> <div class="input"> @elements.input <span class="help-inline">@elements.errors.mkString(", ")</span> </div> </div>
第一个参数是helper.FieldElements 别忘了
然后再建立一个object:
package views.html.helper object myHelper { implicit val fieldConstructor = new FieldConstructor { def apply(elements: FieldElements) = myFileConstructor(elements) } }
最后在需要的html中导入即可:
@import helper.myHelper._
原本就有一个是twitter的:
import helper.twitterBootstrap._*
自定义约束
为Mapping[T]增加约束可以使用verifying(constraints:Constraint[T *)方法( play.api.data.validation.Constraints)
使用如下:"name" -> text.verifying(Constraints.nonEmpty)
自定义约束用verifying实现也很简单 只要向里面传入一个T => Boolean方法即可
例如:
def eanExists(ean: Long) = Product.findByEan(ean).isEmpty
在mapping中:
"ean" -> longNumber.verifying(eanExists(_))
或者简写:
"ean" -> longNumber.verifying(Product.findByEan(_).isEmpty)
也可以带一个错误信息当作第一个参数:
"ean" -> longNumber.verifying("This product already exists.",
Product.findByEan(_).isEmpty)
验证多个域:
因为mapping所得的也是个Mapping[T]所以写起来很简单:
val productForm = Form(mapping( "ean" -> longNumber.verifying("This product already exists!",Product.findByEan(_).isEmpty), "name" -> nonEmptyText, "description" -> text, "pieces" -> number, "active" -> boolean)(Product.apply)(Product.unapply).verifying( "Product can not be active if the description is empty", product => !product.active || product.description.nonEmpty))
这样写有一个问题 错误信息将不会自动生成 因为顶层的Mapping在html中没有id
要自己手动生成 顶层的Mapping产生的错误在Form中是globalError:
@productForm.globalError.map { error => <span class="error">@error.message</span> }
option可选的:
case class Person(name: String, age: Option[Int]) val personMapping = mapping( "name" -> nonEmptyText, "age" -> optional(number) //用optional会返回Mapping[Option[T]] )(Person.apply)(Person.unapply)
list:
如果tags是个List可以写成:
"tags" -> list(text) 他将返回Mapping[List[T]]
如果是手动写的话可以写成:
<input type="text" name="tags[0]">
<input type="text" name="tags[1]">
<input type="text" name="tags[2]">
用helper的话 用repeat方法:
@helper.repeat(form("tags"), min = 3) { tagField => @helper.inputText(tagField, '_label -> "Tag") }
tuple and mapping methods take a maximum of 18 parameters.
嵌套:
val appointmentMapping = tuple( "location" -> text, "start" -> tuple( "date" -> date, "time" -> text), "attendees" -> list(mapping( "name" -> text, "email" -> email)(Person.apply)(Person.unapply)) )
返回的是:
Mapping[(String,(Date, String),List[Person])]
自定义Mapping
除了tuple(返回tuples)和mapping(返回对象) 自定义一个:
改变一个现有的(transform)
新建一个
转换类似于后处理:
如果你有一个Mapping[A] 也有一个A=>B 那可以用transform得到Mapping[B]
val localDateMapping = text.transform( (dateString: String) => LocalDate.parse(dateString), (localDate: LocalDate) => localDate.toString)
不过这样的话 要注意parse可能抛出异常
新建一个formatter
play.api.data.format.Formatter
要实现Formatter[T]的方法:
trait Formatter[T] { def bind(key: String, data: Map[String, String]):Either[Seq[FormError], T] def unbind(key: String, value: T): Map[String, String] val format: Option[(String, Seq[Any])] = None } implicit val localDateFormatter = new Formatter[LocalDate] { def bind(key: String, data: Map[String, String]) = data.get(key) map { value => Try { Right(LocalDate.parse(value)) } getOrElse Left(Seq(FormError(key, "error.date", Nil))) } getOrElse Left(Seq(FormError(key, "error.required", Nil))) def unbind(key: String, ld: LocalDate) = Map(key -> ld.toString) override val format = Some(("date.format", Nil)) }
并向messages中添加:
date.format=Date (YYYY-MM-DD)
error.date=Date formatted as YYYY-MM-DD expected
再用Forms.of讲其转化为Mapping[T]:
val localDateMapping = Forms.of(localDateFormatter)得到Mapping[LocalDate] 因为of的参数是implict上面也写了localDateFormatter是implicit的
也可以写成:
val localDateMapping = Forms.of[LocalDate]
最后使用就可以获得Form了:
val localDateForm = Form(single(
"introductionDate" -> localDateMapping
))
single和tuple是一样的 只有一个参数的话可以用他
文件上传:
如果是单一的文件上传的话:
手工写form的格式:
<form action="@routes.FileUpload.upload" method="post" enctype="multipart/form-data"> <input type="file" name="image"> <input type="submit"> </form>
Action的处理:
def upload() = Action(parse.multipartFormData) { request => request.body.file("image").map { file => file.ref.moveTo(new File("/tmp/image")) Ok("Retrieved file %s" format file.filename) }.getOrElse(BadRequest("File missing!")) }
和form一起的操作:
def upload() = Action(parse.multipartFormData) { implicit request => val form = Form(tuple( "description" -> text, //因为FilePart参数得不到 自己手工写到ignored里 "image" -> ignored(request.body.file("image")).verifying("File missing", _.isDefined)) ) form.bindFromRequest.fold( formWithErrors => { Ok(views.html.fileupload.uploadform(formWithErrors)) },value => Ok) }
于是这个Form就变成了:
Form[(String,Option[play.api.mvc.MultipartFormData.FilePart[play.api.libs.Files.TemporaryFile]])]
用helper的话:
@(form:Form[_]) @helper.form(action = routes.FileUpload.upload,'enctype -> "multipart/form-data") { @helper.inputText(form("description")) @helper.inputFile(form("image")) }
不过这样做的话就不能用upload里的form来传递给空白页了因为在实现里用到了request
def showUploadForm() = Action { val dummyForm = Form(ignored("dummy")) Ok(views.html.fileupload.uploadform(dummyForm)) }
可以用一个什么都不做的表格
form的内容是比较多的 以上的笔记可能有做得不是很容易理解的地方 需要自己多尝试一下 当初学form的时候也用了比较长的时间
相关推荐
Play Framework最新教程(12年),play框架教程
play framework api,play! framework api,play api
play2-war-plugin, 用于 Play Framework 2.x的WAR插件 用于 Play Framework 2.x的 WAR插件Current versions: Play 2.2.x : 1.2.1 Play 2.3.0 -> 2.3.1 : 1.3-beta1 (Scala 2.1
Play Framework Cookbook.pdf
1. Play Framework 介绍 2. 创建和发布 Play 应用 2.1 创建 Play 的工程 2.2 Play 常用指令 2.3 Play 应用的 JVM 调优 3. 如何读取静态资源 4. Play框架的配置文件 5. 使用 Play 框架开发 Java 应用 5.1 HTTP...
playframework javaweb playframework javaweb
Mastering Play Framework for Scala
play framework的一些学习总结,基本概念理解,常用的学习方法等。
Play Framework Cookbook playframework,play! 书中范例代码下载地址: https://github.com/spinscale/play-cookbook 292 pages Publisher: Packt Publishing (September 4, 2011) Language: English ISBN-10: ...
Playframework 1.2.7 sdk zip包
play framework2.01上半部分。
Play framework框架
PlayFramework框架验证.pdf
Play Framework Cookbook
通过简单的代码和思路写了play framework的简单的小例子,包括添加页面进行的routes配置,页面跳转,页面之间的数据传递等方面。暂时未使用h2内置数据库及ArrayList、HashMap在页面之间的数据传递。
Play Framework Essentials 英文原版,学习 play 框架的最佳入门。
PlayFramework框架安全模块.pdf
Leverage the awesome features of Play Framework to build scalable, resilient, and responsive applications First published: May 2015 274page
Play框架肩负了臃肿的企业级java ee规范,易restful为目标专注于开发效率,是java敏捷开发的最佳参考方案
play framework2.01 下半部分