I was trying to send an event from a child presenter to a mother presenter. First i thought the events would simply get lost. I surrounded the fireEvent call with a try/catch block and get this error:
(-:-) 2014-11-06 10:13:26,069 [ERROR] Exception caught: com.google.gwt.core.client.JavaScriptException: (TypeError) __gwt$exception: : Cannot read property 'b' of undefined at Unknown.f2b(mdm-0.js@180:2440) at Unknown.k2b(mdm-0.js@182:2442) at Unknown.t2b(mdm-0.js@51:2448)
My original question got way too long and all the edits may have confused most people. So i constructed a totally stripped-down example, where the error still occurs. This will make it easier to track the error down (i hoped on this way i could solve it myself, but i can't). I also included the imports now, just to be sure not to miss a detail. I have mother presenter (which i also stripped down), which now nearly does not do anything:
package testproject.client.application.policies;
import testproject.client.application.ApplicationPresenter;
import testproject.client.application.policies.test.TestPolicyPresenterWidget;
import testproject.client.events.TestPolicyEvent;
import testproject.client.events.TestPolicyEvent.TestPolicyEventHandler;
import testproject.client.place.NameTokens;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.Presenter;
import com.gwtplatform.mvp.client.View;
import com.gwtplatform.mvp.client.annotations.NameToken;
import com.gwtplatform.mvp.client.annotations.ProxyEvent;
import com.gwtplatform.mvp.client.annotations.ProxyStandard;
import com.gwtplatform.mvp.client.proxy.ProxyPlace;
public class PolicyPresenter extends
Presenter<PolicyPresenter.MyView, PolicyPresenter.MyProxy> implements TestPolicyEventHandler {
private TestPolicyPresenterWidget testPolicyDialog;
@ProxyStandard
@NameToken(NameTokens.policiesPage)
public interface MyProxy extends ProxyPlace<PolicyPresenter> {
}
public interface MyView extends View {
HasClickHandlers getTestPolicyButton();
}
@Inject
PolicyPresenter(EventBus eventBus, MyView view, MyProxy proxy,
TestPolicyPresenterWidget testPolicyDialog) {
super(eventBus, view, proxy, ApplicationPresenter.SLOT_SetMainContent);
this.testPolicyDialog = testPolicyDialog;
}
@Override
protected void onBind() {
super.onBind();
addRegisteredHandler(TestPolicyEvent.TYPE, this);
// Handler for add Policy Button
getView().getTestPolicyButton().addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
Log.debug("Test Policy received click event");
addToPopupSlot(testPolicyDialog);
}
});
}
@Override
protected void onReveal() {
super.onReveal();
}
@Override
protected void onReset() {
super.onReset();
}
@ProxyEvent
@Override
public void onTestPolicyEvent(TestPolicyEvent event) {
Log.debug("TestPolicyCreatedEvent caught");
}
}
I added the @ProxyEvent notation mentioned in the comments, just to make sure...
This view is now also very reduced:
package testproject.client.application.policies;
import javax.inject.Inject;
import testproject.client.model.ContainerPolicy;
import testproject.client.resources.MDMTCellTableResources;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.cellview.client.CellTable;
import com.google.gwt.user.cellview.client.CellTable.Resources;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.view.client.ProvidesKey;
import com.gwtplatform.mvp.client.ViewImpl;
public class PolicyView extends ViewImpl implements PolicyPresenter.MyView {
private static final int pageSize = 15;
interface Binder extends UiBinder<Widget, PolicyView> {
}
private static final ProvidesKey<ContainerPolicy> KEY_PROVIDER = new ProvidesKey<ContainerPolicy>() {
@Override
public Object getKey(ContainerPolicy item) {
return item.getId();
}
};
@UiField
Button testPolicyButton;
@UiField(provided=true)
CellTable<ContainerPolicy> cellTable = new CellTable<ContainerPolicy>(pageSize, (Resources)GWT.create(MDMTCellTableResources.class), KEY_PROVIDER);
public HasClickHandlers getTestPolicyButton() {
return testPolicyButton;
}
public CellTable<ContainerPolicy> getCellTable() {
return cellTable;
}
@Inject
PolicyView(Binder uiBinder) {
initWidget(uiBinder.createAndBindUi(this));
}
}
So now when i click the button, another presenter is shown, using addToPopupSlot(testPolicyDialog);
.
My child presenter (widget) is also totally stripped down now: Presenter:
package testproject.client.application.policies.test;
import testproject.client.events.TestPolicyEvent;
import testproject.client.model.ClientModelProvider;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.HasUiHandlers;
import com.gwtplatform.mvp.client.PopupView;
import com.gwtplatform.mvp.client.PresenterWidget;
import com.gwtplatform.mvp.client.annotations.ProxyEvent;
public class TestPolicyPresenterWidget extends PresenterWidget<TestPolicyPresenterWidget.MyView> implements
TestPolicyUiHandlers {
private final EventBus eventBus;
public interface MyView extends PopupView, HasUiHandlers<TestPolicyUiHandlers> {
CheckBox getEnabled();
CheckBox getEnforced();
TextBox getPolicyType();
TextBox getContainerGroup();
}
@Inject
TestPolicyPresenterWidget(EventBus eventBus, MyView view,
ClientModelProvider clientModelProvider) {
super(eventBus, view);
this.eventBus = eventBus;
}
protected void onBind() {
super.onBind();
Log.debug("EventBus in NewPolicyPresenter is " + eventBus.toString() + " with hashcode " + eventBus.hashCode());
}
@Override
protected void onReveal() {
super.onReveal();
}
@ProxyEvent
@Override
public void createPolicy() {
try {
Log.debug("Click event on ok Button in add policy dialog caught. ");
Log.debug("Firing Event");
eventBus.fireEvent(new TestPolicyEvent());
Log.debug("Firing Event, without stating the eventBus:");
fireEvent(new TestPolicyEvent());
} catch (Exception e) {
Log.error("Exception caught: ",e);
}
}
}
View:
package testproject.client.application.policies.test;
import testproject.client.model.ContainerPolicy;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.inject.Inject;
import com.google.web.bindery.event.shared.EventBus;
import com.gwtplatform.mvp.client.PopupViewWithUiHandlers;
public class TestPolicyView extends PopupViewWithUiHandlers<TestPolicyUiHandlers> implements
TestPolicyPresenterWidget.MyView, Editor<ContainerPolicy> {
interface Binder extends UiBinder<PopupPanel, TestPolicyView> {
}
public interface Driver extends SimpleBeanEditorDriver<ContainerPolicy, TestPolicyView> {
}
@UiField
CheckBox enabled;
@UiField
CheckBox enforced;
@UiField
TextBox policyType;
@UiField
TextBox containerGroup;
@UiField
Button okButton;
@UiField
Button cancelButton;
@Inject
TestPolicyView(Binder uiBinder,EventBus eventBus) {
super(eventBus);
initWidget(uiBinder.createAndBindUi(this));
}
@UiHandler("okButton")
void okButtonClicked(ClickEvent event) {
getUiHandlers().createPolicy();
hide();
}
@UiHandler("cancelButton")
void cancelButtonClicked(ClickEvent event) {
hide();
}
@Override
public CheckBox getEnabled() {
return enabled;
}
@Override
public CheckBox getEnforced() {
return enforced;
}
@Override
public TextBox getPolicyType() {
return policyType;
}
@Override
public TextBox getContainerGroup() {
return containerGroup;
}
}
And, since it is somehow related to JS, the ui.xml:
<!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">
<g:DialogBox modal="false">
<g:caption>
<b>Policy</b>
</g:caption>
<g:HTMLPanel>
<div class="locked">
<div class="lockedpanel float-wrapper container-edit">
<!-- Device block -->
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">Policy</h4>
</div>
<div class="panel-body">
<form class="form-bordered">
<div class="form-group">
<label class="col-sm-4 control-label">Enabled</label>
<div class="col-sm-8">
<g:CheckBox ui:field="enabled" styleName="form-control input-sm"/>
</div>
<label class="col-sm-4 control-label">Enforced</label>
<div class="col-sm-8">
<g:CheckBox ui:field="enforced" styleName="form-control input-sm" />
</div>
<label class="col-sm-4 control-label">Policy Type</label>
<div class="col-sm-8">
<g:TextBox ui:field="policyType" styleName="form-control input-sm"/>
</div>
<label class="col-sm-4 control-label">Container Group</label>
<div class="col-sm-8">
<g:TextBox ui:field="containerGroup" styleName="form-control input-sm"/>
</div>
</div><!-- form-group -->
</form>
</div><!-- panel-body -->
</div><!-- panel-default -->
<div class="float-right">
<g:Button ui:field="okButton" styleName="btn btn-primary btn-bordered">Ok</g:Button>
<g:Button ui:field="cancelButton" styleName="btn btn-primary btn-bordered">Cancel</g:Button>
</div>
</div><!-- lockedpanel -->
</div>
</g:HTMLPanel>
</g:DialogBox>
</ui:UiBinder>
I bind the presenters like this in the ApplicationModule:
package testproject.client.application;
...
public class ApplicationModule extends AbstractPresenterModule {
@Override
protected void configure() {
install(new UiModule());
// Application Presenters
bindPresenter(ApplicationPresenter.class, ApplicationPresenter.MyView.class, ApplicationView.class,
ApplicationPresenter.MyProxy.class);
...
bindPresenter(PolicyPresenter.class, PolicyPresenter.MyView.class, PolicyView.class, PolicyPresenter.MyProxy.class);
bindSingletonPresenterWidget(TestPolicyPresenterWidget.class, TestPolicyPresenterWidget.MyView.class,
TestPolicyView.class);}
}
The error mentioned above happens when i try to access any object inside the createPolicy-method. E.g., when i call this:
Log.debug("Click event on ok Button in add policy dialog caught. ");
Log.debug("Firing Event");
eventBus.fireEvent(new TestPolicyEvent());
i get the error. It does not matter if i use eventBus.fireEvent or fireEvent. It also happens when i try to access other objects. So i guess the problem is not really related to the event handling. But what could cause this?
Thanks for your help so far and for the time reading this...
Are you sure your exception is being logged by the try/catch you added? When you use ViewWithUiHandlers, you need to set your View's UiHandlers manually. In TestPolicyPresenterWidget, you need to add view.setUiHandlers(this)
in its constructor, otherwise getUiHandlers()
will return null in your view.