Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    DynamicForm and ListGrid using same RestDataSource

    I'm having an issue using a DynamicForm and ListGrid which share the same RestDataSource.

    I can use the ListGrid to FETCH and UPDATE items and this works fine. And I can use the DynamicForm to add a new item, which works fine the first time. The first time it's called, it sends only the parameters in the form to the server. The server responds with the full JSON representation of the new domain object which updates the RestDataSource. However, the second time I try to use the form to add a new object, it sends not only the parameters defined in the form, but all the additional attributes of the domain object that were returned on the last use of the form.

    For example, I have a Book with a "title" attribute. The DynamicForm has a single field, "Title". But the data source has all the fields in the domain object, including "id" which is the primary key. The first time I use the form it sends only the "title" field. The second time, it sends the value in the "title" field, and the "id" from new domain object created with the last form submission.

    I'm calling "reset" on the form, which clears the fields, but this doesn't seem to stop it from sending fields which are not part of the form.

    Any suggestions? What am I doing wrong?

    - Greg

    #2
    I also just realized, the first time I call "saveData" (also tried "submit") it submits an ADD request to the server. The second time it submits an UPDATE request. So the object must still be associated with the form even though I'm calling "reset".

    How do I de-associate the object with the form after the Save button is pressed, so that it can be reused to add a new domain object?

    - Greg

    Comment


      #3
      Check out form.editRecord() and form.editNewRecord().

      Comment


        #4
        I'm still getting the problem. Now it is making an ADD request but it is still including field values which are not part of the form. They were present in the JSON response, but some of them aren't even part of the underlying DataSource.

        Here's an example.

        The first time I submit the form, it sends...


        {
        "dataSource":"isc_GrailsDataSource_0",
        "operationType":"add",
        "componentId":"isc_DynamicForm_0",
        "data":{
        "org.gwttest.Author#author":1,
        "title":"test"
        },
        "oldValues":{
        }
        }


        Then the server responds...

        {"response":{"status":0,"data":[{"class":"org.gwttest.Book","id":19,"author":{"class":"Author","id":1},"title":"test"}]}}

        Then the second time I submit the form with a new value in the title field (and after calling "editNewRecord()",


        {
        "dataSource":"isc_GrailsDataSource_0",
        "operationType":"add",
        "componentId":"isc_DynamicForm_0",
        "data":{
        "org.gwttest.Author#author":1,
        "class":"org.gwttest.Book",
        "id":19,
        "author":{
        "class":"Author",
        "id":1
        },
        "title":"testtest"
        },
        "oldValues":{
        "org.gwttest.Author#author":1
        }
        }

        So the problem I'm running into is that the form is sending along these extra fields...

        "class":"org.gwttest.Book",
        "id":19,
        "author":{
        "class":"Author",
        "id":1
        },

        which were part of the JSON response but are not part of the DynamicForm I'm working with. And of these, only the "id" field exists in the RestDataSource object I'm working with.

        How are these getting attached to the form and how can I clear them?

        Thanks for your help,

        - Greg

        Comment


          #5
          That should work. editNewRecord should clear the form allowing for a fresh record to be entered. If this isn't the case please provide a simplified test case.

          Comment


            #6
            Ok, I'll work on that and post it here. What's interesting is that the ListGrid with editable fields works fine with the same type of responses. I can do a FETCH and it displays the correct fields. Then I edit and it sends an UPDATE and gets back the same type of JSON response, and continues to work normally. It's only the DynamicForm that seems to be affected. Calling editNewRecord does indeed set the DSOperationType of the next request to ADD but it doesn't clear the fields.

            I'm wondering if part of the issue is that I'm returning JSON and the fields on the form are being populated by directly assigning the "data" portion of the JSON result, which is creating new attributes on a Javascript object somewhere. I was in the middle of adapting my server component to work with XML rather than JSON to see if that had any affect on this behavior. I'll post a simple test case here when I finish it.

            - Greg

            Comment


              #7
              Can you post just the code you are using to populate the form field values? What you are saying sounds fishy and likely at the root of the problem. I don't think it is related to JSON, just what you are doing.

              Do you populate the form based on a selection from the grid?

              Comment


                #8
                Ok, I made a simple test case. What I found out is it happens every other time the "saveData" method is called on the DynamicForm. I'm using SmartGWT-2.2 and GWT-2.0.3. Here is my code,

                This is the application class.
                Code:
                public class Application implements EntryPoint {
                    /**
                     * This is the entry point method.
                     */
                    public void onModuleLoad() {
                
                    	VLayout main = new VLayout();
                        main.setWidth100();
                        main.setHeight100();
                        main.setLayoutMargin(5);
                        
                        RestDataSource myDataSource = new RestDataSource() {        	
                        	protected Object transformRequest(DSRequest request) {
                        		return super.transformRequest(request);
                        	}
                        	
                        	protected void transformResponse(DSResponse response, DSRequest request, Object data) {
                        		super.transformResponse(response, request, data);
                        	}
                        };
                        
                        myDataSource.setDataFormat(DSDataFormat.JSON);
                        OperationBinding fetch = new OperationBinding();  
                        fetch.setOperationType(DSOperationType.FETCH);  
                        fetch.setDataProtocol(DSProtocol.POSTMESSAGE);
                        fetch.setDataURL("dataSource/test_fetch.js");
                        OperationBinding add = new OperationBinding();  
                        add.setOperationType(DSOperationType.ADD);  
                        add.setDataProtocol(DSProtocol.POSTMESSAGE);
                        add.setDataURL("dataSource/test_add.js");
                        OperationBinding update = new OperationBinding();  
                        update.setOperationType(DSOperationType.UPDATE);  
                        update.setDataProtocol(DSProtocol.POSTMESSAGE);  
                        OperationBinding remove = new OperationBinding();
                        remove.setOperationType(DSOperationType.REMOVE);
                        remove.setDataProtocol(DSProtocol.POSTMESSAGE);
                        myDataSource.setOperationBindings(fetch, add, update, remove);
                        
                        DataSourceIntegerField idField = new DataSourceIntegerField("id", "Id");
                        idField.setHidden(true);
                        idField.setPrimaryKey(true);
                        DataSourceTextField field1Field = new DataSourceTextField("field1", "Field1");
                        
                        myDataSource.setFields(idField,field1Field);
                        
                        final DynamicForm myForm = new DynamicForm();
                        myForm.setDataSource(myDataSource);
                        myForm.setUseAllDataSourceFields(true);
                        
                        Button saveButton = new Button();
                        saveButton.setTitle("Save");
                        saveButton.addClickHandler(new ClickHandler() {
                			@Override
                			public void onClick(ClickEvent event) {
                				myForm.saveData();
                				myForm.editNewRecord();
                			}
                		});
                        
                        main.addMember(myForm);
                        main.addMember(saveButton);
                        
                        final ListGrid grid = new ListGrid();
                        grid.setDataSource(myDataSource);
                        grid.setWidth100();
                        grid.setHeight(150);
                        grid.setAutoFetchData(true);
                        
                        main.addMember(grid);
                        
                        RootPanel.get("main").add(main);
                }
                }


                The two javascript files from which it is pulling data are as follows...

                test_fetch.js
                Code:
                {
                	response: {
                		status: 0,
                		startRow: 0,
                		endRow: 1,
                		totalRows: 1,
                		data: [
                		       {field1:"value1"}
                		]
                	}
                }
                test_add.js
                Code:
                {
                	response: {
                	status: 0,
                	data: [
                	       {field1:"value2",field2:"value"}
                	]
                	}
                }

                So the DataSource is only configured to keep track of the field "field1", but the ADD response is including an extra value "field2".

                Now here is what SmartGWT is sending the server in the requests.

                On page load, it makes a FETCH for the ListGrid...

                Code:
                {
                    "dataSource":"isc_Application$1_0", 
                    "operationType":"fetch", 
                    "startRow":0, 
                    "endRow":75, 
                    "textMatchStyle":"substring", 
                    "componentId":"isc_ListGrid_0", 
                    "data":{
                    }, 
                    "oldValues":null
                }
                On the first call to "saveData",

                Code:
                {
                    "dataSource":"isc_Application$1_0", 
                    "operationType":"add", 
                    "componentId":"isc_DynamicForm_0", 
                    "data":{
                    }, 
                    "oldValues":{
                    }
                }
                On the second call to "saveData",

                Code:
                {
                    "dataSource":"isc_Application$1_0", 
                    "operationType":"add", 
                    "componentId":"isc_DynamicForm_0", 
                    "data":{
                        "field1":"value2", 
                        "field2":"value"
                    }, 
                    "oldValues":{
                    }
                }
                On the third call to "saveData",

                Code:
                {
                    "dataSource":"isc_Application$1_0", 
                    "operationType":"add", 
                    "componentId":"isc_DynamicForm_0", 
                    "data":{
                    }, 
                    "oldValues":{
                    }
                }
                And it alternates back and forth.


                Now, I tried putting the call to "editNewRecord" above "saveData" and that results in the data getting cleared before the response is sent and therefore it doesn't work.

                Am I doing something wrong here?

                - Greg

                Comment


                  #9
                  First thing to clear up is your primary key usage. The datasource caches data based on the primary key. You define one as "id" but you never include that field in your data. This is critical. See the FAQ for details.

                  You should saveData() before editNewRecord() however note that saveData() is asynchronous. Therefore the save is not completed by the time you call editNewRecord(). You will need to register a callback to saveData() and call editNewRecord() there.

                  Comment


                    #10
                    Ah I figured it was something silly I was doing wrong.

                    And there is a convenient DSCallback class for just this purpose :)

                    Thanks so much for your help, I'm really enjoying working with SmartGWT :)

                    - Greg

                    Comment

                    Working...
                    X