Search code examples
jsonxpathsmartgwt

Use of SmarGWT DynamicForm and Form items to created nested JSON with xpath


I have a working SmarGWT datasource that brings back nested JSON as follows:

{username:"tom",password:"pwd",userType:{id:1,name:"admin user type"}}

The sample DataSource looks like:

DataSourceTextField usernameField = new DataSourceTextField("username", "User Name");
DataSourceTextField passwordField = new DataSourceTextField("password", "Password");
DataSourceIntegerField userTypeIdField = new DataSourceIntegerField ("id", "User Type Id");
userTypeIdField.setValueXPath("userType/id");

I can then tie this DS to a listgrid and/or form, and that works ok to display data.

If I create a DynamicForm tied to this same DS, I want to create a new record. I have a username and password textbox which are fine, and I have a SelectItem which gives me back the id to the usertype (1 for Admin, 2 for Oher).

When we get data from this form and look at the JSON sent from the form to the DS, it looks like:

{username:"newuser",password:"newpwd",userTypeId:1}

but I would prefer:

{username:"newuser",password:"newpwd",userType:{id:1}}

because this JSON version of the data would translate nicely into the object I want to send to the controller, which would then file this object. But I do not know if this is possible with the DynamicForm, and/or the SelectItem.

One possibility which I know would work would be to look at the JSON when I send it back for an insert or update. In the transformRequest, I could manually tweak the JSON to remove userTypeId:1 and add userType:{id:1} in it's place.

Or, I could look at a Nested DataSource which I haven't done in a long time.

I am just not sure from the SmarGWT perspective which would be a better mainstream solution.

If I need any more information, let me know, and I will update the question. Thanks in advance for any help!


Solution

  • This was super simple. First in the datasource for UserType, I presume this is very simple. You have usertypeId, userTypeName, UserTypeDescription as follows:

    private DataSourceIntegerField userTypeIdField;
    private DataSourceTextField userTypeNameField;
    private DataSourceTextField userTypeCodeField;
    

    Now let's say you have a datasource for the user, you probably have fields for the userId, username, password, etc, and if UserType is part of that, then you would want to do this:

    private DataSourceField userTypeField;  // notice it is a DataSourcField
    

    As for the declaration:

        userTypeField = new DataSourceField();
        userTypeField.setTitle("User Type");
        userTypeField.setName("userType");
        userTypeField.setTypeAsDataSource(UserTypeDataSource.getInstance());
    

    This is a nice way to do it, if you know you are getting nested JSON or XML data. I have also known cases where, someone has flattened a nested JSON format to the DataSource bu using the XPath seting of a datasourcefield.

    On the SmartGWT DynamicForm side, you can take fields and add an setDataPath binding also, such as the following:

        userTypeField.setName("userType");
        userTypeField.setPickListWidth(210);
        userTypeField.setTitle("User Type");
        userTypeField.setOptionDataSource(userTypeDS);
        userTypeField.setRequired(true);
        userTypeField.setDisplayField("userTypeName");
        userTypeField.setValueField("userTypeId");
        userTypeField.setDataPath("userType/userTypeId");
    

    So, if you had a User DynamicForm, and wanted to set a UserType, the DataPath would preserve the nested JSON, so you'd have something like:

    user:
    {"userId":1,"username":"test","password":"password",
        "userType":{"userTypeId":2}
    }
    

    This may seem like it is so simple now, but maybe this will help someone else out.