I've been spending a lot of time looking at this; including at the client source-code behind the core SmartGWT classes and here is my question: how you set a multi-value property on a DynamicForm; where the value is either an array of int or an array of String?
I've tried setting up a ListGrid inside a CanvasItem, constructing a JavaScriptObject from the contents of the ListGrid; and then calling DynamicForm.setValue() but the DynamicForm somehow completely garbles the JSO.
Here is some sample code:
DataSource file:
First of all, this doesn't even pass validation - for some reason, the client doesn't seem to recognize that what is in the JSO is actually an array of int - I suspect it sees it as either a straight string or an array of string.
Changing the type of the myArray in the DataSource file to "text" does allow it to submit:
but now the problem we have is that the DataSource mangles the contents of the JSO value. For instance, while the JSO array contains this:
this is what actually get submitted:
whereas the request SHOULD look this:
The only way I've found of doing this is by disconnecting the listGrid from the DynamicForm; overriding saveUpdate(), calling DynamicForm.getValuesAsRecord(), setting an int Array on that record, then calling form.editRecord() with the new record and then calling super.saveData(). In other words:
This works; but of course it's a total hack.
I suspect the source of the problem lies in how the setValue() method on the DynamicForm class is put together; namely:
whereas the code for the Record.setValue does:
and
If I understand that code correctly; there's basically no way to insert the contents of a javascript array into a DynamicForm because it assumes that all JavaScriptObjects are single value.
What we urgently need at this point is for DynamicForm to have a setValue(int[] values) and setValue(String[] values) method; or even better: for FormItem to have a setValue(int[] values) and setValue(String[] values) method.
I've tried setting up a ListGrid inside a CanvasItem, constructing a JavaScriptObject from the contents of the ListGrid; and then calling DynamicForm.setValue() but the DynamicForm somehow completely garbles the JSO.
Here is some sample code:
Code:
listGrid.addRecordDropHandler(new RecordDropHandler(){ @Override public void onRecordDrop(RecordDropEvent event) { Vector<Integer> idList = new Vector<Integer>(); //list of existing ids already in selector: int[] exIds = getIds(); for(int exId : exIds) { idList.add(new Integer(exId)); } //newly added ids ListGridRecord[] addedRecords = event.getDropRecords(); for(ListGridRecord addedRecord: addedRecords) { idList.add(addedRecord.getAttributeAsInt("id")); } int[] idArray = new int[idList.size()]; for(int i=0; i<idList.size(); i++) { idArray[i]= idList.get(i).intValue(); } JavaScriptObject jsoArray = JSOHelper.convertToJavaScriptArray(idArray); Log.debug("Setting listGridSelector myArray to jsoArray:" + jsoArray); form.setValue("myArray", jsoArray); } });
Code:
<DataSource ID="myObject" serverType="generic"> <fields> <field name="id" type="sequence" hidden="false" primaryKey="true"/> <field name="myArray" type="int" title="My Array" multiple="true"/> </fields> <serverObject lookupStyle="spring" bean="myObjectDS"/> </DataSource>
Changing the type of the myArray in the DataSource file to "text" does allow it to submit:
Code:
<DataSource ID="myObject" serverType="generic"> <fields> <field name="id" type="sequence" hidden="false" primaryKey="true"/> <field name="myArray" type="text" title="My Array" multiple="true"/> </fields> <serverObject lookupStyle="spring" bean="myObjectDS"/> </DataSource>
Code:
23:59:12.328 [INFO] [myApp] (-:-) 2010-08-02 23:59:12,327 [DEBUG] Setting listGridSelector myArray to jsoArray:7480,7481,7482,7483,7484
this is what actually get submitted:
Code:
Request #1 (DSRequest) payload: { criteria:{ }, values:{ myArray:"7,480,7,481,7,482,7,483,7,484" }, operationConfig:{ dataSource:"myObject", operationType:"add" }, componentId:"isc_OID_97", appID:"builtinApplication", operation:"myObject_add", oldValues:{ } }
Code:
Request #1 (DSRequest) payload: { criteria:{ }, values:{ myArray:[7480,7481,7482,7483,7484] }, operationConfig:{ dataSource:"myObject", operationType:"add" }, componentId:"isc_OID_97", appID:"builtinApplication", operation:"myObject_add", oldValues:{ } }
Code:
@Override public void saveData() { Record recordCopy = getValuesAsRecord(); recordCopy.setValue("myArray",listGrid.getIds()); editRecord(recordCopy); super.saveData(); }
I suspect the source of the problem lies in how the setValue() method on the DynamicForm class is put together; namely:
Code:
public native void setValue(String fieldName, JavaScriptObject value) /*-{ var self = this.@com.smartgwt.client.widgets.BaseWidget::getOrCreateJsObj()(); self.setValue(fieldName, value); }-*/;
Code:
public void setAttribute(String property, int[] value) { JSOHelper.setAttribute(jsObj, property, value); }
Code:
public static native void setAttribute(JavaScriptObject elem, String attr, JavaScriptObject[] value) /*-{ elem[attr] = value; }-*/;
What we urgently need at this point is for DynamicForm to have a setValue(int[] values) and setValue(String[] values) method; or even better: for FormItem to have a setValue(int[] values) and setValue(String[] values) method.
Comment