§フォームの送信
§フォームの定義
play.data
パッケージには HTTP フォームデータの送信とバリデーションを行うヘルパがいくつか含まれています。フォーム送信を処理する最も簡単な方法は、既存のクラスをラップする play.data.Form
オブジェクトを定義することです。
public class User {
public String email;
public String password;
}
Form<User> userForm = Form.form(User.class);
ノート: 内部で行われる値のバインディングには Spring data binder が使われています。
このフォームは HashMap<String,String>
型のデータから User
の値を生成することができます。
Map<String,String> anyData = new HashMap();
anyData.put("email", "[email protected]");
anyData.put("password", "secret");
User user = userForm.bind(anyData).get();
スコープ内にリクエストが存在する場合は、リクエストの内容から直接バインドすることができます。
User user = userForm.bindFromRequest().get();
§制約の定義
JSR-303 (Bean バリデーション) アノテーションを使って、バインディング時にチェックされる制約を追加することができます。
public class User {
@Required
public String email;
public String password;
}
Tip:
play.data.validation.Constraints
クラスには組み込みのバリデーションアノテーションがいくつか含まれています。
トップオブジェクトに validate
メソッドを追加することで、アドホックなバリデーションを定義することもできます。
public class User {
@Constraints.Required
public String email;
public String password;
public String validate() {
if (authenticate(email, password) == null) {
return "Invalid email or password";
}
return null;
}
}
上記の例で返されるメッセージはグローバルエラーになります。
validate
メソッドは、String
, List<ValidationError>
または Map<String,List<ValidationError>>
の型を返すことができます。
validate
メソッドは、アノテーションによる制約を確認し、それらをパスした後に呼び出されます。バリデーションにパスした場合は null
を返されなければなりません。null
でない値 (空の文字列またはリスト) を返すと、バリデーションに失敗したとして処理されます。
フィールドに対してさらにバリデーションを行う場合、List<ValidationError>
が便利かもしれません。例えば、以下のような場合です:
public List<ValidationError> validate() {
List<ValidationError> errors = new ArrayList<ValidationError>();
if (User.byEmail(email) != null) {
errors.add(new ValidationError("email", "This e-mail is already registered."));
}
return errors.isEmpty() ? null : errors;
}
上記の例における email
と同様のエラーコードをキーに持つ Map<String,List<ValidationError>>
も、List<ValidationError>
と同じように使います。
§バインドエラーの処理
バリデーションを定義するということは、一方でバインドエラーを処理しなければならないということです。
if (userForm.hasErrors()) {
return badRequest(views.html.form.render(userForm));
} else {
User user = userForm.get();
return ok("Got user " + user);
}
通常は上記のように、フォームは単にテンプレートにエラーを引き渡します。グローバルエラーは、以下のようにしてレンダリングすることができます:
@if(form.hasGlobalErrors) {
<p class="error">
@form.globalError.message
</p>
}
特定のフィールドに関するエラーは、以下の作法でレンダリングすることができます:
@for(error <- form("email").errors) {
<p>@error.message</p>
}
§フォームに初期値を設定する
よくあるケースとして、編集などのためにフォームに予め値を設定したい場合は、以下のようにします。
userForm = userForm.fill(new User("[email protected]", "secret"));
Tip:
Form
オブジェクトはイミュータブルです。つまり、bind()
やfill()
などのメソッドを呼び出すと、新しいデータで埋められた新しいオブジェクトが返ります。
§モデルと関連しないフォームの処理
Model
と関連しない html フォームからデータを取得する必要がある場合、DynamicForm
を使うことができます:
public static Result hello() {
DynamicForm requestData = Form.form().bindFromRequest();
String firstname = requestData.get("firstname");
String lastname = requestData.get("lastname");
return ok("Hello " + firstname + " " + lastname);
}
§独自の DataBinder を登録する
独自オブジェクトからフォームのフィールド、またはその逆方向のマッピングを定義したいときは、そのオブジェクトのために新たなフォーマッタを登録する必要があります。例えば、JodaTime の LocalTime
オブジェクトのためのフォーマッタを登録する場合は、次のようなコードになります。
Formatters.register(LocalTime.class, new SimpleFormatter<LocalTime>() {
private Pattern timePattern = Pattern.compile(
"([012]?\\d)(?:[\\s:\\._\\-]+([0-5]\\d))?"
);
@Override
public LocalTime parse(String input, Locale l) throws ParseException {
Matcher m = timePattern.matcher(input);
if (!m.find()) throw new ParseException("No valid Input", 0);
int hour = Integer.valueOf(m.group(1));
int min = m.group(2) == null ? 0 : Integer.valueOf(m.group(2));
return new LocalTime(hour, min);
}
@Override
public String print(LocalTime localTime, Locale l) {
return localTime.toString("HH:mm");
}
});
バインドに失敗した場合はエラーキーの配列が作られ、メッセージファイルの中で最初に見つかったものが使われます。この配列は通常、以下のキーを含んでいます:
["error.invalid.<fieldName>", "error.invalid.<type>", "error.invalid"]
これらのエラーキーは、Spring DefaultMessageCodesResolver によって生成されたものの、ルート “typeMismatch” を “error.invalid” で置き換えたものです。
次ページ: フォームテンプレートヘルパーを利用する
このドキュメントの翻訳は Play チームによってメンテナンスされているものではありません。 間違いを見つけた場合、このページのソースコードを ここ で確認することができます。 ドキュメントガイドライン を読んで、お気軽にプルリクエストを送ってください。