Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

It's important that we make sure the datasource has a primaryKey field, without this the datasource caching won't work.

TreeFacadeDS.java

 This is the brains of the server side implementation. There are a couple of sections which I will go over in separate but the main job of this class is to make calls to the underlying datasources (teams and players) based on the parentId from the TreeGrid component. In this sample the only thing we need to do is implement the executeFetch() method.

...

Code Block
themeRDark
languagejava
    private Map convertToTreeItem(final Map data, final String dataSourceName) {
        final Map treeItem = new HashMap();
        treeItem.put("id", dataSourceName + ":" + data.get("id"));
        treeItem.put("dataSourceName", dataSourceName);
        treeItem.put("name", data.get("name"));
        treeItem.put("data", data);
        if (PLAYERS.equals(dataSourceName)) {
            treeItem.put("isFolder", false);
            treeItem.put("parentId", "teams:" + data.get("teamId"));
            treeItem.put("icon", "player.png");
        } else {
            treeItem.put("isFolder", true);
        }
        return treeItem;
    }


Something important to note here is the property called data which is the native record from the underlying datasource. This will be used on the client side when we edit the items in the TreeGrid.

...

For the client side implementation we extend the DataSource class and override the __transformRequest()__ method method. It is important here to set the data protocol to DSProtocol.CLIENTCUSTOM, this will allow us to actually transform the requests. In the constructor we need to define the datasource, in the server side implementation this was done using a ds.xml file but here we define the fields in java.

Code Block
themeRDark
languagejava
    public TreeFacadeClientDS() {
        /**
         * This setting entirely bypasses the Smart GWT comm system. Instead of the DataSource sending an HTTP request to the
         * server, the developer is expected to implement {@link com.smartgwt.client.data.DataSource#transformRequest
         * DataSource.transformRequest} to perform their own custom data manipulation logic, and then call {@link
         * com.smartgwt.client.data.DataSource#processResponse DataSource.processResponse} to handle the results of this action.
         */
        setDataProtocol(DSProtocol.CLIENTCUSTOM);

        // Lets create the primaryKey field id and set it to hidden, this is needed to ensure the caching will work.
        final DataSourceField idField = new DataSourceField("id", FieldType.TEXT);
        idField.setPrimaryKey(true);
        idField.setHidden(true);

        // This is the parent id, also the foreign key field.
        final DataSourceField parentIdField = new DataSourceField("parentId", FieldType.TEXT);
        parentIdField.setForeignKey("id");

        // This is the only field we actually display in the tree, the name.
        final DataSourceField nameField = new DataSourceField("name", FieldType.TEXT);
        // Set the fields on the datasource.
        setFields(idField, parentIdField, nameField);
    }

 

Make sure you have a read of the included comments about the DSProtocol.CLIENTCUSTOM that are included above.

...

Now we need to override the transformRequest() method. This is a bit different to the server side implementation and perhaps less clear on what you
need you need to do. A request to this datasource will pass through this method so here we need to add our facade logic which will delegate to the correct underlying datasource.

Code Block
themeRDark
languagejava
    @Override
    protected Object transformRequest(final DSRequest request) {
        final String requestId = request.getRequestId(); // Grab the requestId, its needed in order to process the response later.
        final DSResponse response = new DSResponse();
        // If this request is of DSOperationType.FETCH, lets handle it.
        if (DSOperationType.FETCH.equals(request.getOperationType())) {
            // Grab the parentId from the criteria
            final String parentId = request.getCriteria().getAttributeAsString("parentId");
            // If there was no parentId then the TreeGrid wants the root nodes so lets return the teams.
            if (parentId == null) {
                // Using DataSource.fetchData() we go and fetch some data from the teams datasource.
                DataSource.get("teams").fetchData(null, new DSCallback() {
                    @Override
                    public void execute(final DSResponse fetchResponse, final Object rawData, final DSRequest fetchRequest) {
                        response.setData(convertToTreeItem(fetchResponse.getDataAsRecordList(), "teams"));
                        processResponse(requestId, response); // This will ensure that the response is processed and returned to the component.
                    }
                });
            } else if (StringUtilsparentId.startsWith(parentId, "teams:")) {
                // Now if we have a parentId and because our parentIds look like "datasourcename:id" we need to string parse it to get the id.
                final String teamId = StringUtilsparentId.substringAftersubstring(parentId, .indexOf(":") + 1);
                // Using DataSource.fetchData() we now use a criteria to fetch all players in the specific team.
                DataSource.get("players").fetchData(new Criteria("teamId", teamId), new DSCallback() {
                    @Override
                    public void execute(final DSResponse fetchResponse, final Object rawData, final DSRequest fetchRequest) {
                        response.setData(convertToTreeItem(fetchResponse.getDataAsRecordList(), "players"));
                        processResponse(requestId, response); // This will ensure that the response is processed and returned to the component.
                    }
                });
            }
        }
        return request.getData();
    }

If you follow the flow you can see that the logic is exactly the same as in the server side datasource we created. We check the parentId and then fire off a request to the appropriate datasource. The way we call the underlying datasource is slightly different here, as you can see we call DataSource.fetchData() instead of creating a DSRequest object. This way requires us to pass a callback implementation through as this is all run client side and using AJAX.

...

Take note of the call to processResponse() in the callback method. This is required in order for the component to get the data back.

Mapping the data

...

Just like in the server side implementation we need to map the data to a format that the TreeGrid will understand so we have a method to solve that here as well. It is very similar to the server side method but uses Record instead of Map. Read from one record and write to a new record.

...