Modelとは
Wicketでは全てのコンポーネントはModelと紐付けることができる。WicketにおけるModelとはデータを入れたり出したりできる器のようなもの。要するに、画面とロジックでの値の受け渡しはModelを経由するということ。
簡単な例
SamplePage.java
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class SamplePage extends WebPage {   private Model sampleText;   private Model sampleLabel;   public SamplePage() {     super();     Form form = new Form("form", new Model());     add(form);     sampleText = new Model();     form.add(new TextField("sampletext", sampleText));     sampleLabel = new Model();     form.add(new Label("samplelabel", sampleLabel));     Button submitButton = new Button("submit", new Model()) {       @Override       public void onSubmit() {         sampleLabel.setObject(sampleText.getObject());       }     };     form.add(submitButton);   } } | 
SamplePage.html
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <html   xmlns="http://www.w3.org/1999/xhtml"   xmlns:wicket="http://wicket.apache.org/">   <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   </head>   <body>     <form wicket:id="form">       前回入力値:<span wicket:id="samplelabel" />       <br />       <input type="text" wicket:id="sampletext" />       <input type="submit" wicket:id="submit" value="送信" />     </form>   </body> </html> | 
実際の表示
初期表示
↓
編集
↓
送信後結果
入力値は、指定したIDに紐付くModelクラスに自動で設定される。またModelクラスにJava内で値を設定することで表示値を変えることもできる。
PropertyModel
基本的には上記のModelクラスで値のやり取りはできるが、入力箇所が多くなればなるほどこの方法だと面倒になる。
- 入力項目全てについてModelを作成するのがめんどくさい
- 入力項目をひとつのBeanにまとめてしまいたい
- 複数のレコードを修正できる一覧表形式の修正画面を作りたい
上記のような場合は、PropertyModelを使うと楽になる。
簡単な例
クラスの変更点は以下。htmlは変更無し。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class SamplePage extends WebPage {   private String sampleText;   private String sampleLabel;   public SamplePage() {     super();     Form form = new Form("form", new Model());     add(form);     form.add(new TextField("sampletext",                            new PropertyModel(this, "sampleText")));     form.add(new Label("samplelabel",                        new PropertyModel(this, "sampleLabel")));     Button submitButton = new Button("submit", new Model()) {       @Override       public void onSubmit() {         sampleLabel = sampleText;       }     };     form.add(submitButton);   } } | 
PropertyModel(Object, String)を使用すると、Object(今回は自分自身を指定)のうちStringに該当するフィールドを探し出し、そこに対してget/setを行ってくれるので、いちいちデータ保持用のModelを作成したり操作したりせずに済む。ちなみに、上記のようにgetter/setterメソッドが無くてもフィールドが存在すれば動いてくれるらしい…が、一応getter/setterメソッドは用意したほうがいいだろう。もちろん、フィールドを用意せずにダミーのgetter/setterを作り、そのメソッド名を指定することもできる。
一覧形式で、複数レコードの修正を行う画面の例
複数件のSampleEntityを画面に一覧表示し、画面でSampleEntityデータを修正できるという感じのサンプル。
クラスは以下。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | public class SamplePage extends WebPage {   private List<SampleEntity> sampleEntityList;   private String sampleLabel;   public SamplePage() {     super();     // 表示用データを設定する(通常はDBから取得したデータなどを設定する)     sampleEntityList = new ArrayList<SampleEntity>();     sampleEntityList.add(new SampleEntity("1", "sample"));     sampleEntityList.add(new SampleEntity("2", "test"));     sampleEntityList.add(new SampleEntity("3", "abc"));     Form form = new Form("form", new Model());     add(form);     // リスト表示用コンポーネント     PageableListView list =       new PageableListView("list", sampleEntityList, 5) {       @Override       protected void populateItem(ListItem item) {         Object record = item.getModelObject();         item.add(new TextField("text1",             new PropertyModel(record, "text1")));         item.add(new TextField("text2",             new PropertyModel(record, "text2")));       }     };     form.add(list);     form.add( new Label("samplelabel",         new PropertyModel(this, "sampleLabel")));     Button submitButton = new Button("submit", new Model()) {       @Override       public void onSubmit() {         StringBuilder sb = new StringBuilder();         for (SampleEntity e : sampleEntityList) {           sb.append(e.toString()).append(" , ");         }         sampleLabel = sb.toString();       }     };     form.add(submitButton);   } } class SampleEntity {   private String text1;   private String text2;   public SampleEntity(String text1, String text2) {     this.text1 = text1;     this.text2 = text2;   }   @Override   public String toString() {     return text1 + ":" + text2;   } } | 
HTMLは以下。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <?xml version="1.0" encoding="UTF-8"?> <html   xmlns="http://www.w3.org/1999/xhtml"   xmlns:wicket="http://wicket.apache.org/">   <head>     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />   </head>   <body>     <form wicket:id="form">       前回入力値:<span wicket:id="samplelabel" />       <input type="submit" wicket:id="submit" value="送信" />       <table border="1">         <thead>           <tr>             <th>text1</th>             <th>text2</th>           </tr>         </thead>         <tbody wicket:id="list">           <tr>             <td><input type="text" wicket:id="text1" /></td>             <td><input type="text" wicket:id="text2" /></td>           </tr>         </tbody>       </table>     </form>   </body> </html> | 
実際の表示
初期表示
↓
編集
↓
送信後結果
そう考えると、普通のModelクラスを使う機会はかなり少ないかもしれない。
CompoundPropertyModel
PropertyModelからさらに手抜きするためのクラスとして CompoundPropertyModel がある。
ModelやPropertyModelでは、コンポーネントをnewする度にモデルもnewしコンポーネントに追加していたが、CompoundPropertyModelを使用した場合コンポーネントにモデルを追加することすら省略できるようになる。
使い方は今までの2つとは若干異なっていて、「追加したいコンポーネントに」モデルを追加するという今までのやり方に対し、CompoundPropertyModelの場合は「追加される方のコンポーネントに」追加することになる。
具体的には、このようなクラスの中身を出力する処理をつくるとして
| 1 2 3 4 5 6 7 8 | class SampleEntity {   public String text1;   public String text2;   public SampleEntity(String text1, String text2) {     this.text1 = text1;     this.text2 = text2;   } } | 
PropertyModelの場合はこのように書くところを
| 1 2 3 4 | SampleEntity entity = new SampleEntity("unko", "moreta"); Form form = new Form("form", new Model()); form.add(new Label("text1", new PropertyModel(entity, "text1"))); form.add(new Label("text2", new PropertyModel(entity, "text2"))); | 
CompoundPropertyModelならこう書ける。
| 1 2 3 4 | SampleEntity entity = new SampleEntity("unko", "moreta"); Form form = new Form("form", new CompoundPropertyModel(entity)); form.add(new Label("text1")); form.add(new Label("text2")); | 
こうすると、Formに追加したCompoundPropertyModelのbeanから、Labelに設定したIDと同名のプロパティを表示するようになる。ただし、コンポーネントのIDとCompoundPropertyModelのbeanのプロパティを一致させなければならないという制約もある。つまり
| 1 2 3 4 | SampleEntity entity = new SampleEntity("unko", "moreta"); Form form = new Form("form", new Model()); form.add(new Label("name",    new PropertyModel(entity, "text1"))); form.add(new Label("comment", new PropertyModel(entity, "text2"))); | 
このようにLabelのIDとbeanのプロパティ名を別にしたい場合はPropertyModelを使おう。
