PlayFrameworkのformでいろいろ試してみた。


普通にFormクラスを利用してのやり方と、やってみたらできたことをメモ。
ちなみにJavaでの開発です。


#version
2.5.10

***
まずはフォームクラスを作成。

```UserForm.java
public class UserForm{

	@Required(message="名前を入力してください")
	public String name;
	
	@Required(message="メールアドレスを入力してください")
	public String email;
	
	@Required(message="電話番号を入力してください")
	@Pattern(regexp = "^(070|080|090)-\\d{4}-\\d{4}$",message="電話番号の形式で入力してください")
	public String telephone;
}
```

入力されるフィールドとValidationを設定します。

次にコントローラー作成。

```FormController.java
package controllers

import com.google.inject.Inject;
import UserForm;
import play.data.Form;
import play.data.FormFactory;
import play.mvc.Controller;
import play.mvc.Result;

public class FormController extends Controller{
	//フォームフィールドを用意
	private Form<UserForm> form;
	
	//コンストラクタでフォームを生成
	@Inject
	public UserController(FormFactory formFactory) {
		this.form = formFactory.form(UserForm.class);
	}

	//フォームを表示するメソッド
	public Result showForm() {
		return ok(form.render(form));
	}
	
	//submitで呼ばれるメソッド
	public Result submit() {
		Form<UserForm> userForm = form.bindFromRequest();
		//エラー時にフォームに戻す
		if(userForm.hasErrors()){
			return badRequest(form.render(userForm));
		}
		
		UserForm user = userForm.get();
		return result.render(user);
	}
}
```

フォーム表示の際はコンストラクタでフォームを作ってviewに渡してあげます。

次にroutesも設定しましょう。

```routes
#フォーム表示
GET    /           controllers.FormController.showForm

#submit
POST   /submit     controllers.FormController.submit

```



続いてviewの作成。helper内では制限があると思っていましたが普通にもできた！

```form.scala.html
@(form: Form[UserForm])
@main(){
	@form.helper(@routes.FormController.submit){
	
		@(helper.inputText(form("name")))
		
		@(helper.inputText(form("email")))
		
		<!-- あとは省略 -->
	}
}
```

上記な感じでフォームができますが、このhelperの記述だとレンダリングされて出てくるformの形が決まっていてちょっと使いづらいなーと。
ちなみに上記でレンダリングされてくるのはこんなん。

```html
<dl class="" id="input_field>
	<dt><lavel for="input">name</label></dt>
	<dd>
		<input type="text" id="name" name="name" value="">
	</dd>
	<!-- エラー検出時はこれが出ます
	<dd class="error">This field is required!</dd>
   	<dd class="error">Another error</dd> -->
   	<!-- 入力制限に応じて出ます
   	<dd class="info">Required</dd>
   	<dd class="info">Another constraint</dd>　-->
</dl>

<dl class="" id="input_field>
	<dt><lavel for="input">email</label></dt>
	<dd>
		<input type="text" id="email" name="email" value="">
	</dd>
	<!-- <dd>省略 -->
</dl>
```

フィールドコンストラクタの自作でいじれるみたいですが、Scalaは全然触ったことないこともあり、別の方法でもっと自由にフォーム画面作りたいなーと思って、helperの中で普通に書いてみたらできました。

```form.scala.html
@(form: Form[UserForm])
@main(){
	@form.helper(@routes.FormController.submit){
		
		@if(form.error("name") != null){
			@form.error("name").message()
		}
		名前:<input type="text" name="name">
		<br>
		@if(form.error("email") != null){
			@form.error("email").message()
		}
		Email:<input type="email" name="email">
		<!-- あとは省略 -->
	}
}
```

上記でもちゃんと動きました。
ただし、helperでの自動生成にたよらず自分で作成するのでエラーメッセージの表示なんかも自分で記述しなければなりません。

***

フォームクラスのアノテーションだけではなく、自分でValidationを作成することもできました。

Controllerのsubmitメソッドで下記

```FormController.java
	public Result submit() {
		Form<UserForm> userForm = form.bindFromRequest();
		//nameの入力値が「aaa」の時にエラーを出す
		if("aaa".equals(equserForm.get().name)){
			ValidationError error = 
				new ValidationError("error", "この名前は使えません。", new ArrayList<>());
			List<ValidationError> errors = new ArrayList<>();
			errors.add(error);
			registerForm.errors().put("nameError", errors);
			return badRequest(form.render(userForm));
		}
	}

```
ValidationErrorオブジェクトを作成してFormにつめる感じです。

viewでのエラーの呼び出し

```form.scala.html
@if(form.error("nameError") != null){
	@form.errors().get("nameError").get(0).message()
}
```

こんな感じで表示させることができました。

フィールドコンストラクタも是非使いこなしてみたいところです。

***
###追記

上記のバリデーションの追加は下記で簡単にできた。

```FormController.java
	public Result submit() {
		Form<userForm> userForm = form.bindFromRequest();
		if("aaa".equals(equserForm.get().name) {
			userForm.reject("nameError", "この名前は使えません");
			return badrequest(form.render(userForm));
		}
	}
```

呼び出し

```form.scala.html
	@if(form.error("nameError") != null){
		@form.error("nameError").message()
	}
```

こっちの方が圧倒的に楽。
Formはよく見てみるとちゃんと色々用意されてました。