Search code examples
gwtmvpuibinder

Replace marker in nested UIBinder Structure / Error handling with MVP


I am using DockLayoutPanel as my main panel. Dependent of the menu I click I change the center-part of the DLP. For example I change either to form1.ui.xml or to form2.ui.xml. Both of these forms have a "marker" implemented to display an error message:

<g:HTMLPanel ui:field="messageblock"/>

I am following the MVP Pattern (I use EventBus for communication) and so far everything works great. The only thing I can't figure out is how to replace the content of messageblock. Or to be more concret how to get access to messageblock from my MainPresenter. The main idea behind this stuff is to bundle the error-handling in one presenter...

I am looking for something like

final Panel panel = DockLayoutPanel.get("messageblock");
panel.add(subwidget);

I appreciate every hint...


Solution

  • Here is the conclusion I came to. Maybe it helps someone else. It's based on what Riley Lark recommended - Thanks to Riley btw.

    RegistrationPresenter here is responsible for the registration process and shows a registration form to the user. The error-message should be displayed as close as possible to the place where the error occurred.

    Without error http://www.mikemitterer.at/fileadmin/stacktrace_imagehosting/screenshot-778.jpg

    An error occurred: Error popped up http://www.mikemitterer.at/fileadmin/stacktrace_imagehosting/screenshot-780.jpg

    Here now a rough description how I implemented this behavior:

    public class RegistrationPresenter implements Presenter {
    
    public interface Display extends StatusDisplay, HasMessageBlock {
        Widget asWidget();
    
        void setData(RegistrationTO registration);
    }
    
    private final Display   display;
    private final EventBus  eventBus;
        ...
    

    as you can see it's Display implements HasMessageBlock:

    public interface HasMessageBlock {
    void showMessage(Message message);
    
    void hideMessage();
        }
    

    There exists a UIBinder-Widget MessageBlock (MessageBlock.ui.xml + MessageBlock.java) (messageblock will be turned to invisible in it's constructor)

        <g:HTMLPanel styleName="errorblock" ui:field="messageblock">
            <div id="errorMsg" class="flurid">
                <div class="row">
                    <div class="column width_15/16">
                        <h3><ui:msg key="errorblock.headline">An error occurred...</ui:msg></h3>
                    </div>
                    <div class="column orientation-right islink width_1/16">
                        <g:Image resource='{res.xgray}' ui:field="image" />
                    </div>
         ...
    

    The Registration-Widget now includes MessageBlock

    <g:HTMLPanel styleName="registration" ui:field="panel">
        <div class="uniForm maxgrid700">
            <h1>
                <ui:msg key="registration.headline">Registration</ui:msg>
            </h1>
            <c:MessageBlock ui:field="messageblock"/>
            <div class="ctrlHolder">
                <p class="label">
                    <em></em>
                    <ui:msg key="registration.name">Name:</ui:msg>
                </p>
         ...
    

    Now, if someone fires a Message

    eventbus.fireEvent(new MessageEvent(new MessageImpl(Message.MESSAGETYPE.ERROR, "Server Error Message")));
    

    every Presenter which has "HasMessageBlock" for it's Display can process/display the message:

            eventBus.addHandler(MessageEvent.TYPE, new MessageEventHandler() {
    
            @Override
            public void execute(final MessageEvent event) {
                display.showMessage(event.getMessage());
            }
        });