AjaxEditable〜まとめ - その1 AjaxEditableLabel

 wicket-extensionsのライブラリーにAjaxEditable〜というクラス群があります。こいつらは何をするクラス達なのかを簡潔に言うと『クリックすると入力可能状態になるAjaxライブラリー』です。
 う〜ん、うまいこと言葉に表せてない・・・orz
というわけで、↓の本家サイトをご覧頂くのが1番早いかと(説明放棄スンマセン・・(;´Д`))

Editable Label Example

今回のエントリーではAjaxEditableLabelについてのメモ。

使い方

 実際にAjaxEditableLabelを使うソースを書く前にAjaxEditableLabelを使わない場合のソースを書いてみます(単にCompany情報を表示するだけのページ。Companyクラスは省略)

CompanyPage.java
public class CompanyPage extends WebPage {
    public CompanyPage() {
        Company company = new Company(1, "company");
        add(new Label<Company>("id", new PropertyModel<Company>(company, "companyId"));
        add(new Label<Company>("name", new PropertyModel<Company>(company, "companyName"));
    }
}
CompanyPage.html
<html>
    <head>
        <title>Company</title>
    </head>
    <body>
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
                <tr>
                    <td><span wicket:id="id"></span></td>
                    <td><span wicket:id="name"></span></td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

まぁ、何の変哲もない普通のWicketのソースですね。んで、これを「ブラウザ上でIDとかNameが表示されている場所をクリックすると、クリックされた箇所がAjaxによりテキストフィールド(input type="text")になる」というソースに書き換えます。↓がそのソース(HTMLは変更なしなのでJavaソースだけ)

public class CompanyPage extends WebPage {
    public CompanyPage() {
        Company company = new Company(1, "company");
        //LabelからAjaxEditableLabelに変更
        add(new AjaxEditableLabel<Company>("id", new PropertyModel<Company>(company, "companyId"));
        add(new AjaxEditableLabel<Company>("name", new PropertyModel<Company>(company, "companyName"));
    }
}

たったこれだけです。LabelクラスをAjaxEditableLabelクラスに変更するだけでIDやNameが表示されている箇所をブラウザ上でクリックするとAjaxによりテキストフィールドに変更されます。

AjaxEditableLabel恐ろしい子

って感じです。とはいえ、このままでは変更内容等をDBに書き込めまなかったりエラー表示ができません。なのでこの状態からさらに下記のように変更します。

public class CompanyPage extends WebPage {
    public CompanyPage() {
        final Company company = new Company(1, "company");
        final FeedbackPanel feedback = new FeedbackPanel("feedback");
        add(feedback.setOutputMarkupId(true));
        add(new AjaxEditableLabel<Company>("id", new PropertyModel<Company>(company, "companyId")){
            @Override
            protected void onError(AjaxRequestTarget target) {
                target.addComponent(feedback);
            }
            @Override
            protected void onSubmit(AjaxRequestTarget target) {
                /** ここでServiceクラスやDaoを使ってデータの更新 */
                // companyService.edit(company);
                super.onSubmit(target);
            }
        }.setRequired(true));
        add(new AjaxEditableLabel<Company>("name", new PropertyModel<Company>(company, "companyName")){
            @Override
            protected void onError(AjaxRequestTarget target) {
                target.addComponent(feedback);
            }
            @Override
            protected void onSubmit(AjaxRequestTarget target) {
                /** ここでServiceクラスやDaoを使ってデータの更新 */
                // companyService.edit(company);
                super.onSubmit(target);
            }
        }.setRequired(true));
    }
}

・onSubmitをオーバーライド

 HTML上で編集可能状態(テキストフィールドの状態)時に該当のテキストフィールドからカーソルを外したりEnterを押したりするとテキストフィールドの情報がSubmitされます。そしてその時に実行されるのがAjaxEditableLabel#onSumitメソッドになります。なのでこのメソッドをオーバーライドし、ServiceクラスやDaoクラスを使って更新処理を実行させます。忘れてはいけないのがsuper.onSubmit(target)を呼び出すこと。これを忘れるとカーソルを外したりEnterを押したりしてもテキストフィールドからLabel(通常の表示状態)に戻らなくなります。

・onErrorをオーバーライド

 通常は何かしらのバリデーションチェックは入るはずなのでそのチェックに引っかかった場合、FeedbackPanelに適切に情報を反映させるためにonErrorメソッドをオーバーライドしてAjaxRequestTarget#addComponentにFeedbackPanelを指定します。その際、事前にFeedbackPanel#setOutputMarkupId(true)は必ず実行させて起きます。

 たったこれだけの事をするだけでAjaxEditableLabelを使えば簡単にAjaxバリバリのカッチョイイ画面が出来上がります。
また、一般的なWebアプリケーションだと
・詳細画面(表示画面)
 ↓
・変更画面
 ↓
・確認画面
 ↓
・完了画面
といったかんじで画面遷移が発生しそうなところもAjaxEditableLabelを使えば画面数節約、ユーザビリティーアップにつながると思います(この部分に関してはAjaxEditableLabelというよりAjaxによりもたらされる効果ですが)。

便利なAjaxEditable〜のクラス群。次回はAjaxEditableMultiLineLabelについてエントリーを書こうかなと思います。