PDA

View Full Version : [FIXED] ComboBox.setValue() doesn't work when allowBlank = false and empty store



chriswesdorp
20 Jul 2009, 11:50 PM
Hi,

I found an issue with setting combobox values which use a 'remote' store to query entries from when allowBlank is set to false. On a FormPanel I added a ComboBox which is attached to a store. The store is not loaded yet when the setValue(D) of the combobox is called via form binding.

In the call for setValue(D) results in a validate triggered by Field.setValue(D). The validate eventually calls ComboBox.doForce() which resets the rawValue for some reason.

The testcase below has a dummy RpcProxy, two comboboxes and a button. The button will set the values for the comboboxes, the first will load properly. The second (with allowBlank = false) doesn't get the value until the trigger button is clicked to load the store.



package nl.chriswesdorp.gxt.gxtcomboboxtest.client;

import com.extjs.gxt.ui.client.data.BaseListLoadResult;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.data.BaseModelData;
import com.extjs.gxt.ui.client.data.ListLoadResult;
import com.extjs.gxt.ui.client.data.ListLoader;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.RpcProxy;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
import java.util.ArrayList;
import java.util.List;

/**
*
* @author c.wesdorp
*/
public class ComboBoxTest implements EntryPoint {

/** Creates a new instance of ComboBoxTest */
public ComboBoxTest() {
}


private int model = 0;

public void onModuleLoad() {
/* Construct a dummy RpcProxy */
RpcProxy<ListLoadResult<ModelData>> proxy = new RpcProxy<ListLoadResult<ModelData>>() {
protected void load(Object loadConfig, AsyncCallback<ListLoadResult<ModelData>> callback) {
List<ModelData> models = new ArrayList<ModelData>();
ModelData model1 = new BaseModelData();
model1.set("id", Long.valueOf(1));
model1.set("code", "model1");
model1.set("descr", "This is model 1");
models.add(model1);

ModelData model2 = new BaseModelData();
model2.set("id", Long.valueOf(2));
model2.set("code", "model2");
model2.set("descr", "The second model");
models.add(model2);

ModelData model3 = new BaseModelData();
model3.set("id", Long.valueOf(3));
model3.set("code", "model3");
model3.set("descr", "The second model");
models.add(model3);

ListLoadResult result = new BaseListLoadResult(models);
callback.onSuccess(result);
}
};

/* Models to be used with setValue() */
final ModelData model1 = new BaseModelData();
model1.set("id", Long.valueOf(1));
model1.set("code", "model1");
model1.set("descr", "This is model 1");
final ModelData model2 = new BaseModelData();
model2.set("id", Long.valueOf(2));
model2.set("code", "model2");
model2.set("descr", "The second model");
final ModelData model3 = new BaseModelData();
model3.set("id", Long.valueOf(3));
model3.set("code", "model3");
model3.set("descr", "The second model");

/* Defines the stores, use two stores because for the second combobox we
* don't want to have a loaded store
*/
ListLoader<ModelData> loader = new BaseListLoader(proxy);
final ListStore<ModelData> store = new ListStore<ModelData>(loader);
final ListStore<ModelData> store2 = new ListStore<ModelData>(loader);

/* Create the form and comboboxes */
final FormPanel form = new FormPanel();
form.setLabelWidth(120);

final ComboBox<ModelData> combo = new ComboBox<ModelData>();
combo.setStore(store);
combo.setDisplayField("code");
combo.setFieldLabel("allowBlank = true");
combo.setName("true");
combo.setForceSelection(true);
form.add(combo);

final ComboBox<ModelData> combo2 = new ComboBox<ModelData>();
combo2.setStore(store2);
combo2.setDisplayField("code");
combo2.setForceSelection(true);
combo2.setAllowBlank(false);
combo2.setFieldLabel("allowBlank = false");
combo2.setName("false");
form.add(combo2);

Button btnSetValue = new Button("Set Value");
btnSetValue.addSelectionListener(new SelectionListener<ButtonEvent>() {
public void componentSelected(ButtonEvent ce) {
/* Set values to the comboboxes */
form.clear();
form.reset();
switch (model++ % 3) {
case 0:
combo.setValue(model1);
combo2.setValue(model2);
break;

case 1:
combo.setValue(model2);
combo2.setValue(model3);
break;

case 2:
combo.setValue(model3);
combo2.setValue(model1);
break;
}
}
});
form.add(btnSetValue);

RootPanel.get().add(form);
}

}
Can this be fixed?

Regards,
Chris

sven
21 Jul 2009, 2:09 AM
Fixed in SVN.

fother
23 Jul 2009, 9:50 AM
add this code


Button btnGetValue = new Button("Get Value");
btnGetValue.addSelectionListener(new SelectionListener<ButtonEvent>() {
@Override
public void componentSelected(ButtonEvent ce) {
Window.alert((String) combo.getValue().get("descr"));
Window.alert((String) combo2.getValue().get("descr"));
}
});
form.add(btnGetValue);


how to reproduce
1 - click in the button "Set Value"
2 - click in the button "Get Value"

will return NPE

stacktrace


[ERROR] Uncaught exception escaped
java.lang.NullPointerException: null
at test.client.Test$3.componentSelected(Test.java:134)
at test.client.Test$3.componentSelected(Test.java:1)
at com.extjs.gxt.ui.client.event.SelectionListener.handleEvent(SelectionListener.java:20)
at com.extjs.gxt.ui.client.event.SelectionListener.handleEvent(SelectionListener.java:1)
at com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:176)
at com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:96)
at com.extjs.gxt.ui.client.widget.Component.fireEvent(Component.java:444)
at com.extjs.gxt.ui.client.widget.button.Button.onClick(Button.java:530)
at com.extjs.gxt.ui.client.widget.button.Button.onComponentEvent(Button.java:277)
at com.extjs.gxt.ui.client.widget.Component.onBrowserEvent(Component.java:760)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1320)
at com.google.gwt.user.client.DOM.dispatchEventAndCatch(DOM.java:1299)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1262)
at sun.reflect.GeneratedMethodAccessor13.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
at com.google.gwt.dev.shell.ie.IDispatchImpl.callMethod(IDispatchImpl.java:126)
at com.google.gwt.dev.shell.ie.IDispatchProxy.invoke(IDispatchProxy.java:155)
at com.google.gwt.dev.shell.ie.IDispatchImpl.Invoke(IDispatchImpl.java:294)
at com.google.gwt.dev.shell.ie.IDispatchImpl.method6(IDispatchImpl.java:194)
at org.eclipse.swt.internal.ole.win32.COMObject.callback6(COMObject.java:117)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:1925)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:2966)
at com.google.gwt.dev.SwtHostedModeBase.processEvents(SwtHostedModeBase.java:235)
at com.google.gwt.dev.HostedModeBase.pumpEventLoop(HostedModeBase.java:558)
at com.google.gwt.dev.HostedModeBase.run(HostedModeBase.java:405)
at com.google.gwt.dev.HostedMode.main(HostedMode.java:232)

fother
23 Jul 2009, 9:54 AM
if remove this line



combo2.setAllowBlank(false);


work fine..

sven
23 Jul 2009, 9:56 AM
That is correct. The value is not in the store, so it cant return anyhting.

fother
23 Jul 2009, 9:58 AM
so why if I set allowBlank equals false work fine?
the value too isnt in the store..

sven
23 Jul 2009, 10:03 AM
There was another issue with that (allowblank) but that is already fixed in SVN. Please only report real bugs here. If something returns null, you cant call something on that again. It wasnt the first time you are doing this.