What is the proper way to use gwt-bootstrap modal with gwt-platform?
Asked Answered
L

4

9

I am constructiong an webapp with Google Web Toolkit using GWT-Platform and GWT-Bootstrap frameworks. Mostly it has been almost flawless until I tried to implement a popup. These frameworks' undestanding of popups seems to be quite different.

GWT-Platform expects a popup widget itself to be an instance of com.google.gwt.user.client.ui.PopupPanel when using the GWTP's RevealRootPopupContentEvent.fire(source, content) or a presenter's addToPopupSlot(child) method.

GWT-Bootstrap's Modal is used like any other widget that is added to the underlying panel but my goal is it to have a separate presenter and view and to possibly fetch it asynchrously with AsyncProvider.

I have tried to make it as a PresenterWidget and using addToSlot(slot, content) to reveal it but it doesn't look quite right. Not all of the styles are applied this way and the close icon (×), doesn't work for example.

I think I am not the first one trying to do something like that so maybe someone has figured out a proper way to make it work.

Thanks!

Lunette answered 21/5, 2012 at 18:45 Comment(1)
The developers are usually pretty responsive to questions asked in their forums: groups.google.com/forum/#!forum/gwt-bootstrapUnwept
P
8

You have to create a view:

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;
    }

}

And a UIBinder file:

<!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>
Pyrology answered 23/5, 2012 at 16:34 Comment(4)
Can you describe what the presenter.hide() method does? It doesn't seem to be a general presenter method.Lunette
In my case it executes placeManager.revealRelativePlace(-1);. You probably won't need it if you don't use a relative place for your popup presenter.Pyrology
I get the dialog from a AsyncProvider and reveal it like this: RevealRootPopupContentEvent.fire(LayoutPresenter.this, result); and result.getView().show(); on the next line so it would show up the second time too. Anyway, thanks @Dominik!Lunette
Hi guys, the question is very good and I have the same problem the answer is even better, but can you describe what PopupViewImpl class is and where do you get it.I use GWT bootstrap "gwt-bootstrap-2.0.4.0-SNAPSHOT" <- the jar I use but didn't find PopupViewImpl. Thanks for help.Gallic
M
3

Your gwtp popup presenter has a view that extends PopUpViewImpl which implements PopupView, and uses a lot of the methods of that interface for displaying the popup (asPopupPanel(), show(), center(), etc).

I'm just starting to get to know gwt-bootstrap (looks great +caalos0), but it seems that Modal doesn't implement PopupView, and therefore cannot be passed to addToPopupSlot in a way it would be displayed automatically by gwtp.

as for the addToSlot() issue, are you using RootLayoutPanel or RootPanel? it could be the reason for addToSlot not working properly, since the gwt-bootstrap Modal widget is attached to the RootPanel on initialization, this can cause weird layout behavior along with an application using RootLayoutPanel as base.

I would try to extend the Modal component, let it implement PopUpView, add it as a field on the PopUpViewImpl attached to your popup presenter, and override the PopUpViewImpl asPopupPanel() function to return the new extended Modal.

Mike answered 23/5, 2012 at 12:57 Comment(0)
H
3

Based on the answer by @dominik I did some improvements, see my Gist. It contains some abstract base classes that can be used for any Modal/PopupView implementation. It's a bit more complex but also cleaner because we don't pass the whole Presenter to the View. The interface for the View to interact with the Presenter when the modal is closed is HasModalUnbind.

You would use these classes as follows. Example presenter:

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

Example view:

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;
    }
}

And the UiBinder XML just for the record:

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

In unbindModal() of ErrorModalPresenter I fire an event which is caught by the parent presenter of ErrorModalPresenter. There the modal presenter is removed from a container and then unbind() is called on the presenter. Of course any other solution is possible in unbindModal().

The base classes assume that modals are one-shot modals that will be removed once they're hidden. This behaviour can be changed in initModal() of ModalPopupViewImpl.

Hower answered 5/7, 2013 at 6:46 Comment(0)
P
0

I believe you will have to made some Glue Code to made it works.

I never used GWT-Platform popups, so I dont know exactly how, but I believe you will have to made a new Class extending PopupPresenter, and made what's needed to made it work.

Also, I was thinking about GWT-Platform days ago... and I'm pretty sure that when first release of GWT-Platform is out, I'll create a new project to made these necessary glue codes.

If you need any help with this, please contact me.

Thanks, sorry about the poor gwt-platform support.

Platen answered 23/5, 2012 at 3:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.