Search code examples
eventsgwtevent-handlinggwtpgwt-platform

GWT, how to fire event from widget or composite using EventBus from HandlerManager


I have widget. I would like to fire an event as follow:

fireEvent(new IndicatorStartEvent("Message"));

But it dosn't work.

Normally I use Presenter for this (GWTP), but now I just would like to have regular widget:

public class FileUploadWidget extends Composite {
    MaterialFileUploader uploader = new MaterialFileUploader();

    @Inject
    public FileUploadWidget(String triggerId, EventBus eventBus) {
        super();
        initWidget(uploader);
        Window.alert("TEST Start");
        fireEvent(new IndicatorStartEvent("Message"));
    }
}

Here is event code:

public class IndicatorStartEvent extends GwtEvent<IndicatorStartEvent.IndicatorHandler> {
    public static Type<IndicatorHandler> TYPE = new Type<IndicatorHandler>();

    public interface IndicatorHandler extends EventHandler {
        void onIndicatorProgressStart(IndicatorStartEvent event);    
    }

    public interface IndicatorHandlers extends HasHandlers {
        HandlerRegistration addStartIndicatorHandler(IndicatorHandler handler);
    }


    private final String message;

    public IndicatorStartEvent(final String message) {
        this.message = message;
    }

    public static Type<IndicatorHandler> getType() {
        return TYPE;
    }

    @Override
    protected void dispatch(final IndicatorHandler handler) {
        handler.onIndicatorProgressStart(this);
    }

    @Override
    public Type<IndicatorHandler> getAssociatedType() {
        return TYPE;
    }

    public String getMessage() {
        return this.message;
    }    
}

This is my app presenter that handle the event:

public class AppPresenter extends TabContainerPresenter<AppPresenter.MyView, AppPresenter.MyProxy> implements AppUiHandlers
, IndicatorStartEvent.IndicatorHandler {
    @ProxyStandard
    public interface MyProxy extends Proxy<AppPresenter> {}
    public interface MyView extends TabView, HasUiHandlers<AppUiHandlers> {}
    @Override
    protected void onBind() {
        super.onBind();
        addRegisteredHandler(IndicatorStartEvent.getType(), this);
    }

    public void onAsyncCallFail(AsyncCallFailEvent event) {
    // fireEvent is executed from: com.gwtplatform.mvp.client;PresenterWidget
        fireEvent(new IndicatorStartEvent("Firing message"));
    }

    @Override
    public void onIndicatorProgressStart(IndicatorStartEvent event) {
        MaterialToast.fireToast("Indicator start: " + event.getMessage());
    }
}

If I fire this event from f.e.: AppPresenter (code above), or GwtRESTY filter/callback ass follow:

class ProgressIndicatorFilter implements DispatcherFilter {
    private AssistedInjectionFactory factory;
    private EventBus eventBus;

    @Inject
    public ProgressIndicatorFilter(AssistedInjectionFactory factory, EventBus eventBus) {
        this.factory = factory;
        this.eventBus = eventBus;
    }
    @Override
    public boolean filter(Method method, RequestBuilder builder) {
        builder.setCallback(factory.createProgressIndicatorCallback(method));
        eventBus.fireEvent(new IndicatorStartEvent("Rest-Gwt Comunication started"));
        return true;
    }
}

It work as expected. But in those working examples it use com.google.web.bindery.event.shared;EventBus The firing event doesnt work from widget, where is used: com.google.gwt.event.shared;HandlerManager;Bus class. This class Bus extends com.google.web.bindery.event.shared.SimpleEventBus which extends the proper EventBus class from com.google.web.bindery.event.shared;EventBus.

So the widget's method fireEvent() use other EventBus.

Can anyone help me with this?

I've red official and this instruction: http://blog.arcbees.com/2015/04/01/gwt-platform-event-best-practices-revisited/ but no luck so far. Please help.


Solution

  • It does not work because your FileUploadWidget uses it's own EventBus and not GWTP one that is also used in all of your Presenters.

    There are two solutions:

    1. Don't use fireEvent(new IndicatorStartEvent("Message")) but use eventBus.fireEvent(new IndicatorStartEvent("Message")) on the injected EventBus inside of your Widget.

    2. Add the IndicatorStartEvent handler to your FileUploadWidget directly instead of using addRegisteredHandler on your Presenter.

    I prefer solution 2:

    public class FileUploadWidget extends Composite {
        MaterialFileUploader uploader = new MaterialFileUploader();
    
        @Inject
        public FileUploadWidget(String triggerId) {
            super();
            initWidget(uploader);
            Window.alert("TEST Start");
            fireEvent(new IndicatorStartEvent("Message"));
        }
    }
    

    In the Presenter or to be precise the View which uses your FileUploadWidget, you add a handler directly to the FileUploadWidget:

    public class UploadView extends ViewWithUiHandlers<UploadUiHandlers> implements UploadPresenter.MyView,IndicatorStartEvent.IndicatorHandler {
    
        @UiField
        FileUploadWidget uploadWidget;
    
        @Inject
        public UploadView(final Binder binder) {
          widget = binder.createAndBindUi(this);    
          uploadWidget.addHandler(new IndicatorStartEvent.Handler(),this);
        }
    
        public void onIndicatorProgressStart(IndicatorStartEvent event) {
           MaterialToast.fireToast("Indicator start: " + event.getMessage());
        }
    }