3

我编写了一个简单的类来包装 JQUEeryUI 对话框。它基本上看起来像这样:

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();

我同意logan的观点,我认为onAttachonLoad事件正在为视图子小部件沉没。我注意到这些方法受到保护。什么是正确接线的正确方法?

更新 2

我已经缩小了问题的范围,因为小部件(通过构造函数传递)没有附加到 DOM - 就小部件本身而言。

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

我相信 Widget Javadoc 为我的情况提供了一些相关信息。

受保护的无效 doAttachChildren()

如果小部件包含一个或多个不在逻辑小部件层次结构中的子小部件(子小部件仅在 DOM 级别上物理连接),则它必须覆盖此方法并为其每个子小部件调用 onAttach()。

鉴于 Dialog 类应该能够使用任何小部件,我不想放弃我的小部件并开始编写大量样板文件,当然必须有一种方法可以优雅地附加小部件。想法?

4

1 回答 1

1

修改你的打开方法:

    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 的 id,因为您可以直接在 DomNode 上实例化 Jquery 对象。修改后的全班:

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 回答