m-namikiの日記

おもしろき こともなき世を おもしろく

Ajaxサンプル

担当している案件でAjaxでゴニョゴニョやる必要が出てきたので、そのサンプルを作成してみました。テキストボックスに文字列を入力して、そこからフォーカスが外れると入力された文字列を元にリストボックスを表示するような形です。


まずはHTMLから。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>wicket-tutorial Ajax Sample</title>
</head>
<body>
<wicket:extend>
<h2>Ajax Samples</h2>
<form wicket:id="appForm" method="post">
<input type="text" wicket:id="condProductName" size="10" /><br/>
<select wicket:id="choices"/><br/>
<input type="submit" wicket:id="doReRender" value="再表示"/><br/>
<span wicket:id="productSelectValue"/><br/>
</form>
</wicket:extend>
</body>
</html>

再表示ボタンをクリックすると、リストボックスで選択されたモノが表示されるようになってます。あと、wicket:extendタグはwicketのページテンプレート用のタグです。これについてはまた別に記事を書いておこうと思うので、今は説明を割愛します。
次にページクラスです。

package jp.co.shantery.wicket.pages;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import jp.co.shantery.wicket.model.ChoiceElement;

import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.ChoiceRenderer;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.ListMultipleChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;

/**
 * @author namiki
 * 
 */
public class AjaxSamplePage extends BaseWebPage {

    private List<ChoiceElement> productSelection;

    @SuppressWarnings( { "serial", "unchecked" })
    public AjaxSamplePage(final PageParameters params) {
        super();
        final Form<Void> appForm = new Form<Void>("appForm");
        add(appForm);

        // ------------------------------------ テキストボックスとチェックボックスの動作設定

        // テキストボックスの定義
        final TextField<String> condProductName = new TextField<String>(
                "condProductName", new Model<String>(""));
        appForm.add(condProductName);

        // リストボックスの定義
        final ListMultipleChoice<ChoiceElement> choices = new ListMultipleChoice<ChoiceElement>(
                "choices", new PropertyModel<List<ChoiceElement>>(
                        AjaxSamplePage.this, "productSelection"),
                new ArrayList<ChoiceElement>(),
                new ChoiceRenderer<ChoiceElement>("name", "id"));
        choices.setOutputMarkupId(true);
        choices.setOutputMarkupPlaceholderTag(true);
        choices.setVisible(false);
        appForm.add(choices);

        // テキストボックスのフォーカスが外れた場合の動作
        condProductName.add(new AjaxFormComponentUpdatingBehavior("onblur") {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                choices.setChoices(createChoiceList(condProductName.getInput()));
                choices.setVisible(true);
                target.addComponent(choices);
            }
        });

        // リストボックスで選択された値を表示するラベル
        final Label productSelectValue = new Label("productSelectValue", "");
        appForm.add(productSelectValue);

        // 再表示ボタン
        final Button doReRender = new Button("doReRender") {
            public void onSubmit() {
                if (productSelection != null) {
                    List<String> labelValue = new ArrayList<String>();
                    for (ChoiceElement elem : productSelection) {
                        labelValue.add(elem.getName());
                    }
                    productSelectValue.setDefaultModelObject(labelValue
                            .toString());
                }
            }
        };
        appForm.add(doReRender);

    private List<ChoiceElement> createChoiceList(String input) {
        List<ChoiceElement> choiceList = Arrays.asList(
                new ChoiceElement("bag", input + "バッグ")
                , new ChoiceElement("shirt", input + "シャツ")
                , new ChoiceElement("cap", input + "帽子")
                , new ChoiceElement("bottom", input + "ズボン")
                , new ChoiceElement("shees", input + "靴")
                , new ChoiceElement("hat", input + "はっと"));
        return choiceList;
    }
}

ChoiceElementはidとnameの2つのフィールドを持つPOJOクラスです。
Component#setOutputMarkupPlaceholderTag(boolean)がキモで、上記の例では

choice.setOutputMarkupPlaceholderTag(true);

としている部分がないといくらAjaxで操作しても表示されません。後はWicket-Ajaxのセオリー通りといった感じですね。