本书第六章以一个实例介绍了Play Framework中Form的使用,如何绑定数据,如何进行验证

一、项目结构和action

《Play for Java》学习笔记(五)Form

《Play for Java》学习笔记(五)Form

二、Play中表单的使用

1. 在Controller中使用Form——处理提交和验证

play.data包中包含了处理HTTP表单数据提交和验证(HTTP form data submission and validation)的一些helpers,一般步骤是先定义一个play.data.Form并包裹进其所用模型类class,如下所示:

Form<User> userForm =Form.form(User.class);
//引入包
import play.data.*;
import static play.data.Form.*;
//
Model—— User Object public class User { public String email; public String password; } //controller—— userForm Form<User> userForm = Form.form(User.class); //1. 定义并包裹模型User类 //This form can generate a User result value from HashMap<String,String> data Map<String,String> anyData = new HashMap(); //2. 写入数据到HashMap--mocking data anyData.put("email", "bob@gmail.com"); anyData.put("password", "secret"); User user = userForm.bind(anyData).get(); //3. 写入数据到表单并绑定给User对象(保存数据) //If have a request available in the scope, bind directly from the request content User user = userForm.bindFromRequest().get();

1.1 在表单中显示预设好的数据——Displaying a form with preset values

《Play for Java》学习笔记(五)Form

public class Products extends Controller {
    private static final Form<Product> productForm = Form.form(Product.class);
    ...
    public static Result details(String ean) {
        final Product product = Product.findByEan(ean);
        if (product == null) {
            return notFound(String.format("Product %s does not exist.", ean));  //处理错误
        }
        Form<Product> filledForm = productForm.fill(product);        //填写product实例中的数据到页面表单productForm中
        return ok(details.render(filledForm));                       //返回(跳转)渲染页面
    }
    ...
}

route是

GET         /products/:ean               controllers.Products.details(ean: String)

1.2 处理表单的输入

《Play for Java》学习笔记(五)Form
① 创建boundForm对象,用于接受从HTTP传入的数据信息,HTTP --> boundForm
boundForm将接受的表单数据传给Product的实例,boundForm --> product
③ 调用produce.save()添加表单数据到Product的实例

1.3 JavaForm(Controller)小结

① 定义表单类用于接收和发送数据  -->  Form<Product> productForm = Form.form(Product.class);
② 把模型中数据写入表单 --> Form<Product> filledForm = productForm.fill(product);
③ 把页面表单的数据写入模型 --> Form<Product> boundForm = productForm.bindFromRequest();
Product product = boundForm.get();
 
product.save();

2. 在模板中使用表单——Form template helpers

在模板中我们可以使用Form template的helpers和helper.twitterBootstrap来处理表单各个项,这些helper会自动生成相应的HTML代码,如:

@helper.form(action = routes.Products.save()) {
    @helper.inputText(productForm("ean"), '_label -> "EAN", '_help -> "Must be exaclty 13 numbers.")
}

会产生如下HTML代码(helper.twitterBootstrap)

<div class="clearfix  " id="ean_field">
    <label for="ean">EAN</label>
    <div class="input">        
        <input type="text" id="ean" name="ean" value="" >
        <span class="help-inline"></span>
        <span class="help-block">Must be exaclty 13 numbers.</span> 
    </div>
</div>

说明: 该helper可用的可选参数如下

'_label -> "Custom label"
'_id ->"idForTheTopDlElement"
'_help -> "Custom help" '_showConstraints ->false
'_error -> "Force an error" '_showErrors ->false

项目中details.scala.html的代码如下:

《Play for Java》学习笔记(五)Form

《Play for Java》学习笔记(五)Form

2.1 引入helper

  • @(productForm: Form[Product]) —— action传入的参数
  • @import helper._ —— Form helpers
  • @import helper.twitterBootstrap._ —— bootstrap helpers

2.2 生成<form> tag

@helper.form(action = routes.Products.save()) { ... }

可在生成的时候加入参数

@helper.form(action = routes.Products.save(),''id -> "form") { ... }

2.3 生成 <input> element

《Play for Java》学习笔记(五)Form

还可以自定义HTML输入

@helper.input(myForm("email")) { (id, name, value, args) =>
    <inputtype="date"name="@name">
}

 2.4 自定义的helper——生成自定义的myFieldConstructorTemplate

@(elements: helper.FieldElements)
<div class="@if(elements.hasErrors) {error}">
<label for="@elements.id">@elements.label</label>
<div class="input">
    @elements.input
    <span class="errors">@elements.errors.mkString(", ")</span>
    <span class="help">@elements.infos.mkString(", ")</span>
</div>
</div>

 保存为views/myFieldConstructorTemplate.scala.html文件,现在就可以使用这个自定义的FieldElements

@implicitField = @{ FieldConstructor(myFieldConstructorTemplate.f) }
@inputText(myForm("email"))

 三、数据绑定

PLay中有三种绑定方式

● 表单绑定(Form binding),见前所述

● URL查询参数绑定(URL query parameters binding):

GET   /products         Products.edit(id: Long) -->  映射到URL:    http://localhost:9000/products?id=12

● URL路径绑定(URL path binding)

GET   /products/:id    Products.edit(id: Long)  -->  映射到URL:   http://localhost:9000/products/12

 1、 简单数据绑定

模型如下:

public class Product {
    public String ean;
    public String name;
    public String description;
}

路由如下:

GET   /products/save   controllers.Products.save()

controller中的部分代码如下:

//创建一个新的Product实例,用来接受HTTP数据
Form<models.Product> productForm = form(models.Product.class).bindFromRequest();
//将从表单得到的数据赋给Product实例
Product product = boundForm.get();
//调用Product的save方法,将数据添加到product实例中
product.save();
...
return redirect(routes.Products.list());

在浏览器中输入http://localhost:9000/product/save?ean=1111111111111&name=product&description=a%20description(该URL的参数即是在表单中填入的数据,通过GET方法传给URL)即可激活Product.save()方法,并转入Product.list()方法,显示从HTTP URL传入的数据。

 2、 复杂数据绑定

假定有两个类Product和Tag,其关系如图《Play for Java》学习笔记(五)Form

//Tag Class
public class Tag {
    public Long id;
    public String name;
    public List<Product> products;
    public Tag(Long id, String name, Collection<Product> products) {
        this.id = id;
        this.name = name;
        this.products = new LinkedList<Product>(products);
        for (Product product : products) {
            product.tags.add(this);
        }
    }
   public static Tag findById(Long id) {
    for (Tag tag : tags) {
      if(tag.id == id) return tag;
    }
    return null;
   }
}
//Product Class
public class Product implements PathBindable<Product>, QueryStringBindable<Product> {
   public String ean;
  public String name;
  public String description;
  public Date date = new Date();
  public Date peremptionDate = new Date();
  public List<Tag> tags = new LinkedList<Tag>();

  public Product() {
  }

  public Product(String ean, String name, String description) {
    this.ean = ean;
    this.name = name;
    this.description = description;
  }
  public static List<Product> findAll() {
    return new ArrayList<Product>(products);
  }

  public static Product findByEan(String ean) {
    for (Product candidate : products) {
      if (candidate.ean.equals(ean)) {
        return candidate;
      }
    }
    return null;
  }

  public static List<Product> findByName(String term) {
    final List<Product> results = new ArrayList<Product>();
    for (Product candidate : products) {
      if (candidate.name.toLowerCase().contains(term.toLowerCase())) {
        results.add(candidate);
      }
    }
}
Tag + Product Class

相关文章:

  • 2021-04-25
  • 2021-08-10
  • 2021-09-15
  • 2021-08-11
  • 2021-07-04
  • 2021-06-29
  • 2021-04-29
  • 2021-11-24
猜你喜欢
  • 2021-07-15
  • 2021-10-13
  • 2021-05-21
  • 2021-08-06
  • 2021-10-22
  • 2021-06-18
  • 2022-12-23
相关资源
相似解决方案