DevExtreme React Grid - Standard Plugins

Oliver's Blog
04 July 2017

This post is part of a series about the DevExtreme React Grid. You can find the introduction and overview to the post series by following this link.

Out of the box, the React Grid comes with several plugins that enable certain control behavior. In a later post, I will show how these plugins can be controlled from React, but for now I will take advantage of the internal functionality of the plugins. Sometimes the term uncontrolled is used for this scenario, hinting at the fact that there is no external influence on a component’s behavior.

Note for clarity that there is one component that is already controlled at this point: the Grid itself, which receives values for its rows and columns from my code.

Plugin categories

All the standard plugins can be sorted into three categories. For details on each plugin that I don’t mention here, please check out the documentation. I will not mention every plugin by name, since I expect the list to change as development progresses.

State

The first category is that of state. All state plugins have names ending in State, like FilteringState and PagingState. These plugins need to be added to the Grid first, i.e. before any plugins from the other categories below.

State plugins provide fields and events for situations where state will be stored elsewhere (the controlled mode mentioned above), and for the uncontrolled mode I’m describing now, they may have defaultXXX fields that enable you to preset the state.

In my sample, shown at the bottom of this post, I’m using all the currently supported state plugins:

<SortingState
  defaultSorting={[{ columnName: "name", direction: "asc" }]}
/>
<PagingState />
<FilteringState />
<GroupingState />
<EditingState onCommitChanges={this.commitChanges} />
<SelectionState />
<RowDetailState />
<ColumnOrderState defaultOrder={["name", "artist", "year"]} />

This configuration supplies default options to two of the plugins, and I’m implementing one of the events to support data saving functionality.

State plugins are imported from DevExpress.ReactGrid in my browser sample, or from @devexpress/dx-react-grid in an app that uses a build environment. State plugins do not implement any UI specific or visualization functionality.

Local functionality

I’ll call the second category local functionality. The plugins of this kind supply implementations of grid features, like grouping and sorting. They do this “locally”, i.e. without interaction with a remote service. While there may be configurable options for these plugins, the general idea is to provide out-of-the-box functionality, like our grid components do on other platforms.

The local functionality plugins depend on the state plugins from above. For example, you cannot use the LocalPaging plugin if you haven’t also added the PagingState. LocalPaging must appear after PagingState to satisfy the dependency.

In my sample, I’m using all currently available local functionality plugins without further configuration:

<LocalSorting />
<LocalFiltering />
<LocalGrouping />
<LocalPaging />

Local functionality plugins are imported in the same way as state plugins, since they also don’t supply visualization functionality.

Visualization

The final category is that of visualization. Plugins in this category are responsible for the rendering of UI elements and information.

Many of these plugins provide options to configure their behavior, and to enable and disable certain features. Some of the plugins also offer options to customize templates they use to render themselves.

The plugins usually have dependencies, and these may include other plugins from the visualization category. For example, the TableHeaderRow depends on the TableView, but it can also utilize information from SortingState and GroupingState (state plugins) as well as DragDropContext (a visualization plugin). Details on dependencies can be found in their documentation (for instance here for TableHeaderRow).

Here are the plugins I’m using in my sample. You can see several options, including one to customize a template.

<DragDropContext />
<TableView allowColumnReordering />
<TableHeaderRow allowSorting allowGrouping allowDragging />
<TableFilterRow />
<TableSelection highlightSelected showSelectAll />
<TableEditRow />
<TableEditColumn allowAdding allowEditing allowDeleting />
<TableRowDetail template={this.tableRowDetailTemplate} />
<PagingPanel allowedPageSizes={[0, 5, 10, 20]} />
<GroupingPanel allowSorting />
<TableGroupRow />

For visualization plugins, order is particularly important. Of course they mostly have to appear after the state and local functionality plugins, but there are also category-internal dependencies. Most plugins must appear after TableView, but even TableView depends on DragDropContext, which is why the latter is listed first in the sample code. Also, the TableGroupRow appears behind all other plugins to correctly combine functionality of grouping, selection, row detail etc.

Note that there is one plugin I’m not using in my sample, which is called VirtualTableView. This provides an alternative to the standard TableView, implementing virtual scrolling.

Plugins of the visualization category are specific to the UI library you use. In my sample, I’m using Bootstrap 3, so these plugins are imported from DevExpress.DXReactGridBootstrap3 or @devexpress/dx-react-grid-bootstrap3. Other UI libraries will be supported in the future, with Material UI being closest to completion. If you use a different supported UI library, you need to import the types from a different source.

Note that in some cases it is possible to accidentally import a type from wrong package. For instance, DragDropContext also exists in DevExpress.DXReactGrid or @devexpress/dx-react-grid. You will receive console error messages due to missing templates if you import a visualization plugin from the wrong package.

Other sample functionality

The sample code implements a template that is used to configure TableRowDetail. This plugin shows an expansion arrow next to each row, and the template renders the content shown if the user expands a row. For real-world applications, this feature enables all sorts of complicated master/detail scenarios, since the template can render whatever you like. For my sample, I chose to use a simple line of output to demonstrate the feature:

tableRowDetailTemplate({ row }) {
  return <div>Details about '{row.name}' by {row.artist}</div>;
}

A function called getRowId is implemented to retrieve a unique id value from a row of data:

getRowId(row) {
  return row.id;
}

This function is configured as a delegate for the Grid component itself. Various plugins may require ids for individual rows, and you will generally have to supply a helper function to extract whatever value (or combination of values) you would like to use to identify rows.

Finally, the sample implements data persistence in component state, in the commitChanges function. The function is configured as the event handler for the onCommitChanges event on the EditingState, so it is executed when the user adds or edits a row and clicks Save, or when the Delete link is used. The details of the inner workings are not relevant and the implementation is supplied only for demonstration purposes.

Note that the commitChanges function is bound to the this context of the App class in the constructor, so the function has access to the App component state.

Try it

Here is the CodePen for the sample described above:

Click here to return to the blog series overview

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.