Как правильно использовать модальную gwt-bootstrap с gwt-platform?

Я создаю веб-приложение с Google Web Toolkit с использованием GWT-Platform и GWT-Bootstrap. В основном это было почти безупречно, пока я не попытался реализовать всплывающее окно. Представление этих рамок о всплывающих окнах кажется совершенно другим.

GWT-Platform ожидает, что сам всплывающий виджет будет экземпляром com.google.gwt.user.client.ui.PopupPanel при использовании GWTP RevealRootPopupContentEvent.fire(source, content) или ведущий addToPopupSlot(child) метод.

Модал GWT-Bootstrap используется, как и любой другой виджет, который добавляется к базовой панели, но моя цель состоит в том, чтобы у него был отдельный презентатор и представление и, возможно, асинхронно получать его с AsyncProvider.

Я попытался сделать это как PresenterWidget и используя addToSlot(slot, content) чтобы раскрыть это, но это выглядит не совсем правильно. Не все стили применяются таким образом, и значок закрытия (×), например, не работает.

Я думаю, что я не первый, кто пытается сделать что-то подобное, поэтому, возможно, кто-то нашел правильный способ заставить это работать.

Спасибо!

4 ответа

Решение

Вы должны создать вид:

public class MyPopupView extends PopupViewImpl implements MyView {

    protected Widget widget;

    public interface MyPopupViewUiBinder extends
            UiBinder<Widget, MyPopupView> {
    }

    @UiField(provided = true)
    Modal dialogBox;

    private MyPresenter presenter;

    @Inject
    public MyPopupView(final MyPopupViewUiBinder uiBinder,
            final EventBus eventBus) {
        super(eventBus);
        setUpDialog(); // Provides UiField => Before initWidgets
        initWidget(uiBinder.createAndBindUi(this));
    }

    // DialogBox must be overridden to let the presenter handle changes onUnload
    private void setUpDialog() {
        dialogBox = new Modal() {

            @Override
            protected void onUnload() {
                MyPopupView.this.hide();
            }
        };

        dialogBox.setTitle("Some title");
    }

    @Override
    public void setPresenter(final MyPresenter presenter) {
        this.presenter = presenter;
    }

    @Override
    public final void hide() {
        dialogBox.hide();
        presenter.hide();
    }

    @Override
    public void setAutoHideOnNavigationEventEnabled(final boolean autoHide) {
        // TODO Auto-generated method stub
    }

    @Override
    public void setCloseHandler(
            final PopupViewCloseHandler popupViewCloseHandler) {
        // TODO Auto-generated method stub
    }

    @Override
    public void setPosition(final int left, final int top) {
        // TODO Auto-generated method stub
    }

    @Override
    public void show() {
        dialogBox.show();
    }

    @Override
    public void center() {
        dialogBox.show();
    }

    @Override
    public Widget asWidget() {
        return widget;
    }

    protected final void initWidget(final Widget widget) {
        this.widget = widget;
    }

}

И файл UIBinder:

<!DOCTYPE ui:UiBinder SYSTEM "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    xmlns:g='urn:import:com.google.gwt.user.client.ui'
    xmlns:b='urn:import:com.github.gwtbootstrap.client.ui'>

    <b:Modal title="Some Title" ui:field="dialogBox">
        <!-- Your content -->
    </b:Modal>
</ui:UiBinder>

Основываясь на ответе @dominik, я сделал некоторые улучшения, см. Мой Gist. Он содержит некоторые абстрактные базовые классы, которые можно использовать для любой реализации Modal/PopupView. Это немного сложнее, но и чище, потому что мы не проходим весь Presenter к View, Интерфейс для View взаимодействовать с Presenter когда модал закрыт HasModalUnbind,

Вы бы использовали эти классы следующим образом. Пример докладчика:

public class ErrorModalPresenter extends ModalPopupPresenter<ErrorModalPresenter.MyView> {

    public interface MyView extends ModalPopupView {
        DivElement getErrorMessage();
    }

    private final ErrorEvent error;

    @Inject
    public ErrorModalPresenter(final EventBus eventBus,
                               final MyView view,
                               @Assisted final ErrorEvent error) {

        super(eventBus, view);
        this.error = error;
    }

    @Override
    public void unbindModal() {
        ErrorDismissEvent.fire(this, this);
    }

    @Override
    protected void onBind() {
        super.onBind();

        //noinspection ThrowableResultOfMethodCallIgnored
        getView().getErrorMessage().setInnerText(error.getCause().getMessage());
    }
}

Пример вида:

public class ErrorModalView extends ModalPopupViewImpl implements ErrorModalPresenter.MyView {

    @UiField(provided = true)
    Modal errorModal;

    @UiField
    DivElement errorMessage;

    interface Binder extends UiBinder<Widget, ErrorModalView> {}

    @Inject
    public ErrorModalView(final EventBus eventBus,
                          final Binder uiBinder) {

        super(eventBus);

        errorModal = initModal();
        initWidget(uiBinder.createAndBindUi(this));
    }

    @Override
    public DivElement getErrorMessage() {
        return errorMessage;
    }
}

И UiBinder XML просто для записи:

<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
             xmlns:g='urn:import:com.google.gwt.user.client.ui'
             xmlns:b='urn:import:com.github.gwtbootstrap.client.ui'>

    <b:Modal ui:field='errorModal' title='Error'>
        <g:HTML>
            <div ui:field='errorMessage'/>
        </g:HTML>

        <b:ModalFooter>
            <b:Button text='Close' dismiss='MODAL'/>
        </b:ModalFooter>
    </b:Modal>

</ui:UiBinder>

В unbindModal() из ErrorModalPresenter Я запускаю событие, которое ловит родительский ведущий ErrorModalPresenter, Там модальный ведущий удаляется из контейнера, а затем unbind() называется на ведущего. Конечно, любое другое решение возможно в unbindModal(),

Базовые классы предполагают, что модалы - это одноразовые модалы, которые будут удалены после их скрытия. Это поведение может быть изменено в initModal() ModalPopupViewImpl,

Ваш докладчик всплывающих окон gwtp имеет представление, которое расширяет PopUpViewImpl, который реализует PopupView, и использует множество методов этого интерфейса для отображения всплывающих окон (asPopupPanel(), show(), center() и т. Д.).

Я только начинаю узнавать gwt-bootstrap (выглядит великолепно +caalos0), но кажется, что Modal не реализует PopupView, и поэтому не может быть передан в addToPopupSlot таким образом, как он будет автоматически отображаться gwtp.

Что касается проблемы addToSlot(), используете ли вы RootLayoutPanel или RootPanel? это может быть причиной того, что addToSlot не работает должным образом, так как модальный виджет gwt-bootstrap присоединяется к RootPanel при инициализации, это может вызвать странное поведение макета вместе с приложением, использующим RootLayoutPanel в качестве основы.

Я бы попытался расширить модальный компонент, позволить ему реализовать PopUpView, добавить его в виде поля в PopUpViewImpl, присоединенного к вашему докладчику всплывающих окон, и переопределить функцию PopUpViewImpl asPopupPanel(), чтобы вернуть новый расширенный модальный.

Я полагаю, что вам придется сделать немного кода клея, чтобы он заработал.

Я никогда не использовал всплывающие окна GWT-Platform, поэтому я не знаю точно, как, но я верю, что вам придется создать новый класс, расширяющий PopupPresenter, и сделать все необходимое для того, чтобы он работал.

Кроме того, я думал о GWT-Platform несколько дней назад... и я почти уверен, что когда выйдет первый выпуск GWT-Platform, я создам новый проект для создания этих необходимых клейких кодов.

Если вам нужна помощь с этим, пожалуйста, свяжитесь со мной.

Спасибо, извините за плохую поддержку gwt-платформы.

Другие вопросы по тегам