DevExpress: Updating a dxGrid widget.

DevExpress has a line of web controls that I’ve been playing with.
https://js.devexpress.com/

On the whole, I think they are good. I have found the documentation to be plentiful, but the specifics can be scattered in different places. Which is why I’m sharing my experience with their data grid control. It’s more formally called a dxDataGrid. My goal was to simply have an input tag that could hold a foreign key ID. When that value changed, I wanted the data grid to be updated with JSON data from a WebAPI. Pretty common scenario, but I didn’t see a copy & paste example in the documentation that didn’t use Angular. So here is an example to save you some time.

I’m limiting the code to only the relevant parts. It basically displays a list of applications. When you click on one, the data grid gets populated with a list of roles for the application.

Index.cshtml

<div id="applicationList"></div>
<input id=”applicationExternalID” />
<div id=”applicationRolesGrid”></div>

In terms of the markup, this is pretty minimal. DevExpress offers some tag helpers that you can use to create the controls, but they stick a bunch of java script in the middle of the HTML, and I rather keep the java script in separate files. All the configuration can be done in JS.

Index.js

(function ($) {
    
    var applicationList = $("#applicationList").dxList({
        dataSource: DevExpress.data.AspNet.createStore({
            key: "ApplicationID",
            loadUrl: "https://localhost:44356/application/GetApplicationsByTenant",
            onBeforeSend: function (method, ajaxOptions) {
                ajaxOptions.xhrFields = { withCredentials: true };
            }
        }),
        height: 400,
        itemTemplate: function (data) {
            return $("<div>").text(data.DisplayName);
        },
        onItemClick: function (e) {
            var externalID = e.itemData.ExternalID;
            $("#applicatonExternalID").val(externalID);
            $("#DisplayName").text(e.itemData.DisplayName);

            roleSource = DevExpress.data.AspNet.createStore({
                key: "ApplicationRoleID",
                loadUrl: "https://localhost:44356/application/GetApplicationRolesByApplication",
                loadParams: { externalID: externalID },
                onBeforeSend: function (method, ajaxOptions) {
                    ajaxOptions.xhrFields = { withCredentials: true };
                }
            })
            applicationRolesGrid.option('dataSource', roleSource);
            applicationRolesGrid.refresh();
        }
    }).dxList("instance");

    var rolesSource = DevExpress.data.AspNet.createStore({
        key: "ApplicationRoleID",
        loadUrl: "https://localhost:44356/application/GetApplicationRolesByApplication",
        onBeforeSend: function (method, ajaxOptions) {
            ajaxOptions.xhrFields = { withCredentials: true };
        }
    })

    var applicationRolesGrid = $("#applicationRolesGrid").dxDataGrid({
    
        columns: [{
            dataField: "ApplicationRoleID",
            width: 80
        }, {
            dataField: "DisplayName"
        }],

        paging: {
            pageSize: 10
        }
    }).dxDataGrid("instance");

}(jQuery))

So the first thing to take note of is the data stores that are used. DevExpress has created a project on GitHub that allows their client side widgets (controls) to consume data from a ASP.NET web api.
https://github.com/DevExpress/DevExtreme.AspNet.Data
In the case of loading data for the list of applications, I was able to provide the data store with a URL to get the data. You can pass it credentials, and specify a key for each unique record. This is a pretty easy use case. To tell the dxList to use the data store, just set the list’s dataSource parameter to an instance of the data store. The rest is pretty much magic.

I actually create a second data store to get the list of roles for the selected application. This one will require the use of a parameter called loadParams. The WebAPI has a function that takes in a string called externalID, so the loadParams is provided with an object that contain the property externalID.

public async Task<IActionResult> GetApplicationRolesByApplication(string externalID)

This parameter should change every time a different item is clicked in the dxList. So I’ve added a handler to the dxList.onItemClick event. When that happens, I need to update the loadParams object with the new externalID. Here is the sticky party. I expected that I could call the data grid’s refresh method, and it would make the call to the web api and display the new data. But that’s not the case. I actually had to reassign the dxGrid’s dataSource property. That can be done by using the option function to reassign the dataSource property.

applicationRolesGrid.option('dataSource', roleSource);

This is really pretty simple to use, you have to find all the bits that need to be touched. If you know of better ways to do this, feel free to post in the comments.