`

【playframework2笔记整理】4、form

 
阅读更多

本文来自: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属性就可以了 dataMap对象
也可以借助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的时候也用了比较长的时间 

 

0
0
分享到:
评论

相关推荐

    Play Framework2本教程

    Play Framework2是一个强大的Java和Scala应用开发框架,它以其简洁的API、快速的开发周期以及对Web标准的紧密集成而闻名。本教程旨在为初学者和有经验的开发者提供全面的指导,帮助他们掌握Play Framework2的核心...

    play framework api,play! framework api,play api

    2. **异步编程**:Play Framework基于Akka框架,支持非阻塞I/O和异步处理,提高了Web应用的并发性能。 3. **路由系统**:Play Framework的路由文件定义了URL到Action的映射,允许开发者灵活地控制请求处理逻辑。 4...

    playframework中文教程.zip

    Play Framework 是一个开源的Web应用框架,主要针对Java和Scala开发者设计,它的核心理念是简化开发流程,提高开发效率,并且特别强调了RESTful架构风格。这个“playframework中文教程.zip”压缩包很可能是为了帮助...

    Play Framework Cookbook.pdf

    目前最新的版本是 Play 2.x 系列,该版本在 Play 1.x 的基础上进行了全面改进,采用了更为先进的设计理念和技术栈。 - **主要特性**: - **非阻塞 I/O**:Play Framework 采用异步非阻塞 I/O,这意味着它可以处理...

    Play framework框架

    Play Framework框架 Play Framework框架是一种基于Java的软件框架,旨在提高开发效率和提供REST式的架构风格。该框架可以让开发者继续使用他们喜欢的开发环境或繻库,不需要切换到另一种语言、IDE或者其他繻库。 ...

    PlayFramework框架验证.pdf

    PlayFramework提供了一套完整的验证机制,允许开发者通过声明式的方式定义模型(Model)或表单(Form)的验证规则,并在控制器(Controller)中进行校验。 PlayFramework的验证机制使用了play.data.validation包下...

    play2-war-plugin, 用于 Play Framework 2.x的WAR插件.zip

    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 -&gt; 2.3.1 : 1.3-beta1 (Scala 2.1

    play framework 框架个人笔记

    Play Framework 是一个开源的Web应用框架,以Java和Scala为后盾,致力于提供简洁、高效、可测试的开发体验。本文将深入探讨Play Framework的基本概念、常用命令、Eclipse调试方法、模式、控制器、工具包、session...

    Play Framework

    1. Play Framework 介绍 2. 创建和发布 Play 应用 2.1 创建 Play 的工程 2.2 Play 常用指令 2.3 Play 应用的 JVM 调优 3. 如何读取静态资源 4. Play框架的配置文件 5. 使用 Play 框架开发 Java 应用 5.1 HTTP...

    Play Framework Cookbook

    ### Play Framework Cookbook 知识点解析 #### 一、Play Framework 概览 - **定义与背景**:Play Framework 是一款基于 Java 和 Scala 的高性能、轻量级 Web 开发框架。它采用 RESTful 架构设计,支持热重载功能,...

    Play Framework应用程序框架 v2.7.9.zip

    4. **模块化结构**:Play Framework支持模块化,允许开发者选择或创建自己的模块来扩展框架功能。 5. **强大的路由系统**:通过简洁的路由定义,可以将URL映射到控制器方法,方便处理HTTP请求。 6. **模板引擎**:...

    playframework javaweb

    playframework javaweb playframework javaweb

    Play Framework Cookbook(PlayFramework )(September 4, 2011)

    ### Play Framework Cookbook 知识点概览 #### 一、编写自定义渲染方法 - **知识点概述**:Play Framework 允许开发者编写自己的渲染方法,从而返回定制化的格式,如PDF、RSS或ATOM feed响应。 - **应用场景**:在...

    playframework 框架学习之路 1

    Play Framework 是一个基于Java和Scala的开源Web应用框架,它遵循模型-视图-控制器(MVC)架构模式。在“Playframework框架学习之路 1”中,我们可能要探讨这个框架的基础概念、安装过程以及如何创建一个简单的应用...

    Mastering Play Framework for Scala

    Mastering Play Framework for Scala

    playFramework1.2.3

    2. **无XML配置**:Play Framework倾向于使用Java注解和纯代码配置,避免了XML配置文件的繁琐,降低了学习曲线,同时也减少了出错的可能性。 3. **简单的路由系统**:通过简单的 routes 文件,你可以定义URL与控制...

    play framework2.01 part1

    play framework2.01上半部分。

    Play framework 2.0 -第一个应用程序

    《Play Framework 2.0 - 创建你的第一个应用程序》 Play Framework 2.0 是一个开源的Web应用框架,它基于Scala和Java语言,遵循“模式-动作”(Action)架构,提供了一种轻量级、敏捷开发的方式。本篇文章将引导你...

    play,play framework资料大全

    Play Framework 是一个基于Java的开源Web应用框架,它遵循MVC(模型-视图-控制器)架构模式,致力于简化Web应用程序的开发过程。这个资料大全包含了许多关于Play Framework的重要资源,帮助开发者深入理解和高效使用...

    playframework框架项目部署文档

    《Play Framework框架项目部署详解》 Play Framework是一个强大的、基于Java和Scala的开源Web应用程序框架,它采用模型-视图-控制器(MVC)架构模式,以简洁的API和直观的开发体验受到开发者喜爱。本篇文章将详述...

Global site tag (gtag.js) - Google Analytics