Обертка диалогового окна GWT JQueryUI не прикрепляет виджет

Я написал простой класс, который является оболочкой для диалога 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();

FYI 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 и считаю, что события onAttach или onLoad опускаются за просмотры дочерних виджетов. Я замечаю, что эти методы защищены. Что было бы прямо сейчас, чтобы правильно их подключить?

Обновление 2

Я сузил проблему, заключающуюся в том, что виджет (переданный через конструктор) не прикреплен к DOM - что касается самого виджета.

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

Я считаю, что Widget Javadoc предоставляет некоторую важную информацию для моей ситуации.

защищенная пустота doAttachChildren ()

Если виджет содержит один или несколько дочерних виджетов, не входящих в логическую иерархию виджетов (дочерний элемент физически подключен только на уровне DOM), он должен переопределить этот метод и вызвать onAttach () для каждого из своих дочерних виджетов.

Учитывая, что класс Dialog должен иметь возможность работать с любым виджетом, я не хочу отказываться от своего виджета и начинать писать множество шаблонов, безусловно, должен быть способ элегантно прикрепить виджет. Идеи?


person LoneWolf    schedule 04.10.2012    source источник
comment
В чем причина использования jQuery?   -  person Andrei Volgin    schedule 04.10.2012
comment
Мне удалось заставить большинство панелей раскрытия информации работать в аккордеоне jQuery с помощью UiBinder. Можете ли вы включить сюда еще какой-нибудь код или ссылку на него? Я полагаю, что это связано с тем, как GWT поглощает события.   -  person logan    schedule 05.10.2012
comment
Спасибо за комментарий, логан, я добавил еще источник   -  person LoneWolf    schedule 05.10.2012


Ответы (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) {
                [email protected]::onClose()();
                _self = null;
            }
        });
    }-*/;

А остальное пусть останется нетронутым;)

РЕДАКТИРОВАТЬ: на самом деле вам даже не нужно генерировать идентификатор DomNode, поскольку вы можете создать экземпляр объекта Jquery непосредственно на DomNode. Весь ваш класс после модификаций:

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) {
                [email protected]::onClose()();
                _self = null;
            }
        });
    }-*/;

    final native void open(Element element) /*-{
        $wnd.jQuery(element).dialog("open");
    }-*/;
}
person Tomasz Gawel    schedule 08.10.2012
comment
Вы легенда. Ревизия мне тоже нравится; замена id на элемент. Очень хорошая работа :) Я счастлив, что теперь могу двигаться дальше .. спасибо! - person LoneWolf; 09.10.2012