フォームの利用
次に、データ送受の基本であるフォームについてです。Webでは、データのやり取りと言うとフォームを送信してサーバ側で受け取る、というのが基本でした。しかし、Vaadinでは、ここまでフォームは登場しませんでした。フォームなど用意しなくとも、個々のコンポーネントから値を取得し処理できますから、あまりフォームの必要性が感じられないのは確かです。
実は、Vaadinにも、フォームのためのクラスはちゃんと用意されています。「Form」というもので、これを利用することで、フォームとして入力コンポーネントをまとめることができます。しかし、Formの働きはそれだけではありません。入力された情報を管理するための機能を提供してくれるのです。
入力関係のコンポーネントには、バリデーションを行うための機能が用意されています。Formは、Form内に組み込まれているコンポーネント類のバリデーションをチェックし、すべてが正しく入力されているかどうかを確認の上で処理を行います。
またFormは、あらかじめフォーム用に用意したモデルクラスをデータの保管用に設定することで、モデルのオブジェクトとしてフォームデータを管理します。これにより、いくつもの入力データをまとめて扱えるようになるのです。
モデルクラスの作成
では、実際にFormを利用してみましょう。今回は、「名前」「パスワード」「メール」「メモ」といった項目のあるフォームを用意することにします。まずは、フォームのデータを管理するためのモデルクラスを用意しましょう。
package com.example.myvaadin;
import java.io.Serializable;
public class MyFormData implements Serializable {
private String name = "";
private String pass = "";
private String mail = "";
private String comment = "";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPass() {
return pass;
}
public void setPass(String pass) {
this.pass = pass;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
}
MyFormDataクラスは、Serializableなごく普通のBeanクラスです。先のサンプルと同様、保管する項目はprivateフィールドとして用意しておき、そのアクセサを用意しておきます。今回は、コンストラクタなどは特に用意していません。これはFormによって利用されるものなので、デフォルトコンストラクタだけで十分なのです。
ファクトリーの作成
続いて、ファクトリークラスを作成します。ファクトリーは、フォームに使うフィールドを生成するためのもので、FormFieldFactoryというインターフェースとして用意されています。これがimplements済みとなったDefaultFieldFactoryというものも用意されていますが、今回はFormFieldFactoryをimplementsして新しいファクトリークラスを作ります。
package com.example.myvaadin;
import com.vaadin.data.Item;
import com.vaadin.data.validator.StringLengthValidator;
import com.vaadin.ui.*;
public class MyFormFieldFactory implements FormFieldFactory {
@Override
public Field createField(Item item, Object propertyId, Component uiContext) {
TextField field = null;
if ("name".equals(propertyId)){
field = new TextField("名前");
field.setRequired(true);
field.setRequiredError("名前は必須です。");
field.addValidator(new StringLengthValidator("名前は10文字以内で記入ください。",1,10,false));
}
if ("pass".equals(propertyId)){
field = new TextField("パスワード");
field.setSecret(true);
field.setRequired(true);
field.setRequiredError("パスワードは必須です。");
field.addValidator(new StringLengthValidator("パスワードは4文字以上12文字以内で記入してください。",4,12,false));
}
if ("mail".equals(propertyId)){
field = new TextField("メール");
field.setRequired(true);
field.setRequiredError("メールアドレスは必須です。");
}
if ("comment".equals(propertyId)){
field = new TextField("メモ");
field.setRows(5);
field.addValidator(new StringLengthValidator("メモは最大500文字以内で記入してください。",0,500,false));
}
field.setWidth("200px");
return field;
}
}
ファクトリークラスでは、「createField」というメソッドを用意します。これが、Fieldを作成して返すもので、Formではこのメソッドを呼び出してFieldを作成していくようになっています。このメソッドではItem、Object、Componentといった引数が渡されます。ここでは、プロパティのIDが渡される第2引数のObjectの値をチェックし、それに応じて必要な設定をしたFieldを作成し返すようにしています。
各Fieldでは、入力を制限するため「setRequired」「addValidator」といったメソッドを呼び出しています。前者はメソッドを必須項目にするためのもの、後者はFieldにバリデータを組み込むためのものです。ここでは、StringLengthValidatorというバリデータクラスを使い、入力された文字数をチェックするようにしています。
このファクトリークラスの作成が、Form利用の最大のポイントといってよいでしょう。モデルクラスのフィールドと照らし合わせ、それぞれのFieldとモデルクラスのフィールドが正しく対応するように設計する必要があります。
