GWTで通常のWebアプリを書く変態

GWTといえばクライアントサイドのコードを書くというイメージが非常に強いですが、実は既存のHTMLにイベントを付与するという使い方も可能です。

たとえば以下のようなHTMLがあったとしましょう。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <title>MainModule</title>
        <script type="text/javascript">
            var isomorphicDir = "gwttest.Calc/sc/";
        </script>
    </head>
    <body  >
        <script type="text/javascript" language="javascript"
        src="gwttest.Calc/gwttest.Calc.nocache.js"></script>

        <form id="form" method="get" action="result.jsp">
            <input type="text" id="param1" name="param1">+
            <input type="text" id="param2" name="param2">=
            <button id="add" type="button">計算</button>
        </form>

    </body>
</html>

GWTとSmartGWTの設定が少し入っている以外は通常の足し算をするWEBアプリですよね。ただし、submitボタンはわざと用意していないのでそれを実行する必要があります。


ではこれにイベントを付与してみます。

package gwttest.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.dom.client.InputElement;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.TextBox;
import com.smartgwt.client.util.SC;

public class Calc implements EntryPoint{
    FormElement form = FormElement.as(DOM.getElementById("form"));
    Button button = Button.wrap(DOM.getElementById("add"));
    TextBox text1 = TextBox.wrap(DOM.getElementById("param1"));
    InputElement text2 = InputElement.as(DOM.getElementById("param2"));
    
    public void onModuleLoad() {
        
        //初期値
        text1.setText("1");
        text2.setValue("2");
        
        button.addClickHandler(new ClickHandler() {
            public void onClick(ClickEvent event) {
                //必須入力のチェック
                if(text1.getText().length() == 0 ||
                        text2.getValue().length() == 0){
                    Window.alert("入力してください");
                    return;
                }

                //数値型かどうかのチェック
                try{
                    Integer.parseInt(text1.getText());
                    Integer.parseInt(text2.getValue());
                }catch(NumberFormatException ex){
                    SC.say("数値で入力してください");
//                    Window.alert("数値で入力してください");
                    return;
                }

                //クライアントサイドでのバリデーションがすんでる
                form.submit();
            }
        });
    }

}

見てわかるとおりIDを利用してマッピングが可能です。

フォームとテキストフィールドの2つ目をElementでマッピングしています。これはHTMLと直に1:1で関連付けをすることが可能です。自由度は高いのですが、細かい挙動を完全に知っている必要があります。たとえばInputのtypeごとに種類が異なるわけではありません。すべてInputElementです。

ボタンを一つ目のテキストはウィジェットとして関連付けをしています。これはいわゆる通常のGUIコンポーネントとして扱えるものです。イベントや各種設定が楽になっています。

違いはテキスト2種を見てもらえればわかります。ElementのほうはValueプロパティをアクセスしているのに対して、ウィジェットのほうはTextプロパティといった感じです。


では、実行してみます。まず必須なのに入力しなかった場合。
http://shin.cside.com/diary/2009/1128-01.png


続いて数値に変換できなかった場合。こちらはSmartGWTを使っています。
http://shin.cside.com/diary/2009/1128-02.png
綺麗なダイアログですね。でも、見てわかるとおり使い方は非常に簡単ですね。



Elementは一から作り出すことも可能です。DOM操作と組み合わせてなんでも可能なわけですが、一から作るのであれば最初からウィジェットを新規作成した方がはるかに楽です。


今回の程度であればjavascriptを書いてもかまわないでしょう。でも複雑なGUI操作を始めるとjavascriptでの生産性の低さがネックになってきます。

ショーケースにあるようなものをjavascriptだけで作っていくのは大変です。大概の場合サーバーサイドのコードも書くため、言語は二種類必要うになってしまいますし。


SmartGWTのコンポーネントGWTコンポーネントとあわせて使えますので、まずは便利なダイアログやデータグリッド等効果がわかりやすいものだけに特化して使うとかきめておくと勉強も少なくてすみますのでいいかもしれません。ツリー等もjavascriptで実装していくのはたるいので効果が大きいですね。