3

JQUEryUI ダイアログをラップする単純なクラスを作成しました。基本的には次のようになります。

public class Dialog extends Composite
{
    final String id;

    public Dialog(IsWidget body) {
            initWidget(body.asWidget());
            id = DOM.createUniqueId();
            getElement().setId(id);
    }

    public void create() {
            create(id);
    }

    public void open() {
            open(id);
    }

    final native void create(String id) /*-{
            $wnd.jQuery("#" + id).dialog({ autoHide: true });
    }-*/;

    final native void open(String id) /*-{
            $wnd.jQuery("#" + id).dialog("open");
    }-*/;
}

初期化されたビューを渡します (uibinder テンプレートを使用しています)。ビューにチェックボックスなどの単純な HTML 要素しか含まれていない場合は問題なく動作しますが、開示パネルやセル リストなどの複雑なウィジェットが含まれている場合、パネルはクリック イベントに応答しません。開示パネルが開かず、セル リストもイベントに応答しませんが、これらのビューは両方とも、「GWT ポップアップ パネル」に格納される前は正常に機能していました。

アップデート

ダイアログがどのように初期化されるかを示すその他のソース コードを次に示します。

HasDialog parent = (HasDialog) body;
Dialog dialog = parent.getDialog();
dialog.open();

参考までに HasDialog は、ウィジェットによって継承された単なるインターフェイスです。

interface HasDialog { Dialog getDialog(); }

たとえば、開示パネル ウィジェットを含むウィジェットは次のようになります。

final Dialog dialog;

@Override
public Dialog getDialog()
{
    if (dialog == null) {  // only one instance
        dialog = new Dialog(this);
        dialog.create();
    }

    // dialog buttons and events have been commented out

    return dialog;
}

GWT ポップアップ パネルと一緒に使用すると正常に動作するため、ウィジェットに内部的な問題はないと想定できます。

PopupPanel popup = new PopupPanel();
popup.setWidget(body);
popup.center();

ローガンに同意します。ビューの子ウィジェットに対してonAttachまたはonLoadイベントが沈んでいると思います。これらのメソッドが保護されていることに気付きました。これらを適切に配線するためにすぐにできることは何でしょうか?

更新 2

ウィジェット自体に関する限り、(コンストラクターを介して渡された)ウィジェットがDOMにアタッチされていないという問題を絞り込みました。

public void open()
{
    open(id);
    if (getWidget().isAttached() == false) {
        Window.alert("Widget not attached");
    }
}

Widget Javadoc は、私の状況に関連する情報を提供してくれると思います。

protected void doAttachChildren()

ウィジェットに、論理ウィジェット階層にない 1 つ以上の子ウィジェットが含まれている (子は DOM レベルでのみ物理的に接続されている) 場合、このメソッドをオーバーライドし、子ウィジェットごとに onAttach() を呼び出す必要があります。

Dialog クラスはどのウィジェットでも動作できるはずなので、ウィジェットをダウンキャストして定型文をたくさん書き始めたくはありません。ウィジェットをエレガントにアタッチする方法が必要です。アイデア?

4

1 に答える 1

1

open メソッドを変更します。

    public void open() {
        onAttach();
        RootPanel.detachOnWindowClose(this);
        open(id);
    }

クローズハンドラに追加:

    void onClose() {
        if(RootPanel.isInDetachList(this)) {
            RootPanel.detachNow(this);
        }
        else {
            onDetach();
        }
    }

ダイアログの作成中に onclose ハンドラを登録します。

    final native void create(String id) /*-{
        var _self = this;
        $wnd.jQuery("#" + id).dialog({ 
            autoHide: true, 
            close: function(event, ui) {
                _self.@your.package.Dialog::onClose()();
                _self = null;
            }
        });
    }-*/;

そして、残りはそのままにしておきます;)

編集: 実際、DomNode で Jquery オブジェクトを直接インスタンス化できるため、DomNode の ID を生成する必要さえありません。変更後のクラス全体:

public class Dialog extends Composite {

    public Dialog(IsWidget body) {
        initWidget(body.asWidget());
    }

    public void create() {
        create(getElement());
    }

    public void open() {
        onAttach();
        RootPanel.detachOnWindowClose(this);
        open(getElement());
    }

    void onClose() {
        if(RootPanel.isInDetachList(this)) {
            RootPanel.detachNow(this);
        }
        else {
            onDetach();
        }
    }

    final native void create(Element element) /*-{
        var _self = this;
        $wnd.jQuery(element).dialog({ 
            autoHide: true, 
            close: function(event, ui) {
                _self.@your.package.Dialog::onClose()();
                _self = null;
            }
        });
    }-*/;

    final native void open(Element element) /*-{
        $wnd.jQuery(element).dialog("open");
    }-*/;
}
于 2012-10-08T11:30:23.063 に答える