WicketではAjaxを使うこともできる。ここではテキストフィールドに文字を入力してボタンを押すと、入力した内容がリストで表示されるというページを作ってみる。

まずHTML側にはテキストフィールドやボタン、リスト表示用のコンテンツなどを用意する。ここではリスト1のHomePage.htmlを修正してリスト7のようにした。

リスト7 HomePage.html

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC 
      "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns:wicket="http://wicket.apache.org">
  <head>
    <title></title>
    <link wicket:id='stylesheet'/>
  </head>
  <body>
    <span wicket:id='mainNavigation'/>

    <b><span wicket:id="message" >ここにメッセージが表示される。</span></b>

    <!-- 追加した部分 -->
    <form wicket:id="form">
      <input wicket:id="messageField" type="text" value="" size="50"/>
      <input wicket:id="ajaxButton" type="submit" value="入力"/>
      <div wicket:id="listViewContainer"><ul>
          <li wicket:id="listView"><span wicket:id="label"></span></li>
      </ul></div>
    </form>

  </body>
</html>

フォーム、テキストフィールド、ボタンにはそれぞれ「form」「messageField」「ajaxButton」というIDを付けてある。また、入力したメッセージがリスト表示されるのは「listView」というIDが付いている部分である。「listViewContainer」は、listViewのためのコンテナとして利用されるものだ。

Javaプログラム側であるHomePage.javaはリスト8のようになった。

リスト8 HomePage.java

package jp.co.mycom.howto.wicket;

import java.util.*;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.*;
import org.apache.wicket.markup.html.list.*;
import org.apache.wicket.model.Model;

public class HomePage extends BasePage {
    public HomePage() {
        // 表示する文字をセットしたLabelを作成し、ページに追加
        this.add(new Label("message", "Hello Wicket!"));

    // ここから追加分
        // フォームを作成
        final Form form = new Form("form");

        // フォームにテキストフィールドを追加
        final TextField field = new TextField("messageField", new Model<String>());
        field.setOutputMarkupId(true);
        form.add(field);

        // リストビュー用のコンテナを作成してフォームに追加
        WebMarkupContainer container = new WebMarkupContainer("listViewContainer");
        container.setOutputMarkupId(true);
        form.add(container);

        // コンテナにリストビューを追加
        container.add(new ListView<String>("listView", new ArrayList<String>()) {
            @Override
            protected void populateItem(ListItem<String> item) {
                String labelString = item.getModelObject();
                item.add(new Label("label", labelString));
            }
        });

        // Ajaxを利用したボタン
        AjaxButton ajaxButton = new AjaxButton("ajaxButton") {
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                // テキストフィールドの内容をリストビューに追加
                TextField field = (TextField)form.get("messageField");
                String textString = field.getValue();
                ListView listView = (ListView)form.get("listViewContainer:listView");
                List<String> list = listView.getModelObject();
                list.add(textString);
                target.addComponent(form.get("listViewContainer"));
            }
        };
        form.add(ajaxButton);

        this.add(form);
    }
}

順番に説明する。まずフォームおよびテキストフィールドに対応するコンポーネントは、それぞれorg.apache.wicket.markup.html.formパッケージのFormクラスおよびTextFieldクラスになる。TextFieldオブジェクトに対して行っている「field.setOutputMarkupId(true);」は要素のID(wicket:idではなく通常のid属性の方)を有効にするかどうかの設定である。もしDOMを操作する場合にはIDが必要となるためtrueにしておかなければならない。

コンテンツをリスト表示するにはorg.apache.wicket.markup.html.list.ListViewを使うと便利である。ListViewはabstractなクラスであり、populateItem()メソッドを実装して使用する。このメソッドではListViewの要素の扱い方を設定する。今回の例では要素を格納するモデルとしてListを使用するように、コンストラクタの第2引数にArrayListオブジェクトを渡している。そしてpopulateItem()は次のようにすることで、各要素を「label」というIDに関連付けて表示するように実装してある。

リスト9

            protected void populateItem(ListItem<String> item) {
                String labelString = item.getModelObject();
                item.add(new Label("label", labelString));
            }

HTML側で対応するのは次の部分だ。

リスト10

<li wicket:id="listView"><span wicket:id="label"></span></li>

このListViewオブジェクトは、直接ページに貼り付けないで、org.apache.wicket.markup.html.WebMarkupContainerというコンテナを使って配置している。今回の例ではListViewをAjaxの処理のターゲットとして動作させたいのだが、そのために使用するAjaxRequestTargetには直接Viewオブジェクトを追加することができないため、このように間にコンテナを挟ませる必要があるわけだ。

肝心のボタンにはorg.apache.wicket.ajax.markup.html.form.AjaxButtonクラスを利用する。このクラスもabstractであるため、ボタンが押された場合の処理を決めるonSubmit()メソッドを実装する形で使用する。このonSubmit()に渡されるAjaxRequestTargetがAjaxの処理のターゲットを表している。したがってここのオブジェクトにコンテンツを追加すればページの描画に反映される。

ここでは、まずonSubmit()に渡されたFormオブジェクトからTextFieldとListViewを取得し、TextFieldに入力された文字列をListViewのモデルオブジェクトに追加している。そして最後にListViewのコンテナである「listViewContainer」をAjaxRequestTargetに追加する。

ここまでできたら、プロジェクトをサーバにデプロイしてWebブラウザからアクセスしてみよう。最初は図6のようにテキストフィールドとボタンが表示される。ここで適当な文字を入力してボタンを押せば、図7のように押した文字が下部にリスト形式で追加されていくはずだ。

図6

図7

ちなみに右下の「WICKET AJAX DEBUG」はAjax用のデバッグコンソールであり、Ajaxによるリクエストパラメータなどを見れるようになっている。本番環境ではweb.xmlの設定によって消すことができる。

このように、WicketならばたとえAjaxを使う場合でも特別な設定ファイルを必要とせず、HTMLとJavaプログラムだけで全てが完了してしまう。設定ファイルを用いない分だけコードは複雑になりやすいが、コンポーネントの扱いはSwingとよく似ているので、GUIプログラミングに慣れた開発者であればそれほど苦労なく使いこなすことができるだろう。

多くのフレームワークではさまざまな設定を外部ファイルに分離することでコードの記述量を削減しているが、その分オブジェクト指向のコンポーネントモデルの外で行う作業が増えてしまう。Wicketが目指すのはその逆で、コンポーネントモデルの中で全てを完結させようというものだ。したがって、純粋にプログラムコードだけですべてを行いたいという開発者には特にお勧めのフレームワークと言える。