Oliver's Blog
  • Announcing a React Data Grid Release Candidate

    The first Release Candidate (RC) of the DevExtreme React Grid is now available! Many thanks to all users who provided feedback during the beta phase – your help is very much appreciated!

    The following paragraphs summarize the changes we made during the beta.

    React Data Grid RC

    API stabilization and improvements

    Improving and stabilizing the APIs was our primary focus during the beta phase. Our goal was to provide a powerful API, consistent throughout the Grid plugins, that would also be easy and intuitive to understand, and convenient to use. We revised all types and identifiers, and we developed rules to ensure naming stability and ease of maintenance for the future.

    Improved customization experience

    A second goal we had was to improve the Grid customization experience, since we had received lots of feedback and questions on this topic before the beta started. After much detailed investigation and experimentation we finally found a suitable solution. We now provide access to default components used by the Grid plugins, which enormously simplifies customization of invididual components, as well as the implementation of custom behaviors, for example the handling of row or cell click events.

    Custom TableRow

    ColumnChooser, reworked

    Our initial implementation of the Column Chooser as a separate component seemed too different from the general plugin approach used in the Grid. We came back to this feature and decided to reimplement it, adhering to our plugin architecture. Starting with the RC, the ColumnChooser is not separate anymore from the Grid component – just add it like any other Grid plugin and that’s it!

    The visual appearance of the ColumnChooser was also changed. It is now displayed as a drop-down menu in the Grid header.


    The Future

    We had great success with the feedback we received from our users, which made it possible for us to understand priorities, and to build the most convenient developer experience for the React Grid. Of course we will continue to work in the same way, so: if you feel that something still isn’t as easy as it should be, we are all ears! Please contact us via our GitHub page.

  • Scale (Axis) Breaks with DevExtreme HTML5 Chart and Range Selector (v17.2)

    This post covers the DevExtreme Chart and Range Selector widgets, which are available for jQuery, as Angular components, ASP.NET MVC and ASP.NET Core MVC controls, and as Knockout bindings.

    In v17.2, the dxChart and dxRangeSelector controls introduce a small but very useful feature: scale breaks a.k.a. axis breaks. This solves the problem where values in a chart have such a high amplitude that some series points are rendered very small, possibly almost invisible but certainly too small to interact with.

    Chart without scale breaks

    Scale breaks make such charts more useful by skipping parts of the scale. You can declare a collection of custom scale breaks, which is supported for both the value and the argument axis. The breakStyle property allows visual customization of the break appearance.

    valueAxis: { 
      breaks: [{ 
        startValue: 1, 
        endValue: 14.6 
      }, { 
        startValue: 95, 
        endValue: 318 
      }, { 
        startValue: 17.2, 
        endValue: 95 
      breakStyle: {
        line: 'waved' // default value

    The widget can also calculate the scale breaks automatically for the value axis:

    valueAxis: { 
      autoBreaksEnabled: true, 
      maxAutoBreakCount: 3 

    Chart with scale breaks

    Finally, custom scale breaks are implemented for the dxRangeSelector widget:

    scale: { 
      startValue: 15000, 
      endValue: 150000, 
      breaks: [{ 
        startValue: 20000, 
        endValue: 35000 
      }, { 
        startValue: 100000, 
        endValue: 145000 

    Range selector with scale breaks

    Try it now!

    You can get v17.2 right now via npm.

    npm install devextreme@17.2

    Please let us know your thoughts about this feature!

  • Localization, Formatting and Mask Improvements for DevExtreme HTML5 Widgets (v17.2)

    Localization is an important part of an application. I have recently covered a number of localization aspects in my blog post about localization for DevExtreme. Note that this post has been updated to reflect the news in v17.2.

    Localization, Formatting and Mask Improvements

    We received lots of feedback about practical scenarios and we have made significant improvements. It is now possible to specify custom formats without the need to include Globalize or Intl. Globalize is a powerful library that provides rich formatting and localization capabilities, but many applications require localization for one language only. Using Globalize is a non-trivial step, so we decided to directly support a number of scenarios where the power of Globalize isn’t really needed. Intl is much easier to use, but developers can still save time by taking advantage of our new built-in feature set.

    In addition, we have added format support to the NumberBox and we have improved the behavior of masks in the TextBox.

    Built-in support for custom formats

    When working with numbers and dates, developers often need to define specific value formats. Prior to v17.2, DevExtreme supported only a few predefined formats out of the box. For custom formats, you had to use a 3-rd party i18n library (Globalize), or alternatively implement custom formatter and parser functions. Both approaches were more complicated than necessary for the use case.

    In v17.2 you can now use custom formats in all widgets that support formatting. You can set a custom format with just simple format string, based on an LDML-like pattern. There is no need to define formatter or parser functions.

    Date formatting examples

    Displaying DataGrid column values with the full month name:

    Grid with format

    Using a custom format for the DateBox that displays the date, the time in 12-hour format, and milliseconds:

    DateBox custom format

    Number formatting

    We have used feedback from v17.1 to analyze the most scenarios most important for our users, and implemented solutions for number formatting that will make the jobs of application developers easier. Meet the new NumberBox with custom formatting!

    Formatting functionality in the NumberBox involves not only the formatting of the value itself, but also intuitive behavior of the input caret. Additional symbols can be added while the user inputs data (for example, the delimiters), and the caret keeps the correct position.

    NumberBox Currency

    It used to be a major inconvenience to make minor changes to a value format when using our editors, because 3rd-party libraries were required. Now we directly support the following use cases with a single “format” option:

    Adding a prefix and/or postfix

    With the support of format strings in NumberBox, you can easily display the unit for a number. For instance, use format: "#0 px" to denote pixels or format: "$#0" for a currency format.

    NumberBox with prefix and postfix

    For a currency format that observes localization, use format: "currency":

    NumberBox with localized currency

    Showing localized fractional and digit grouping delimiters

    Different cultures have different number representation rules, different decimal delimiters, and digit grouping rules.

    Using Intl or Globalize with the setting format: "#,##0.##”, the elements , (the thousands separator) and . (the decimal separator) are automatically replaced with the separators from your locale:

    NumberBox number formatting

    If you don’t use either Intl or Globalize, the built-in localization engine enables you to customize decimal and thousands separators manually, and the format strings use these settings.

    Defining a precision in the NumberBox

    The patterns not only specify number format, they also control input, preventing typing of incorrect characters and controlling the number of decimal places. Here are some examples:

    "#0.##" - 2 decimal places, the fractional part is not mandatory

    NumberBox Floating Point

    "#0.000" - 3 decimal places, the fractional part is mandatory

    NumberBox Fixed Point

    Advanced scenarios

    Of course the NumberBox still supports the 3rd-party localization libraries Globalize and Intl in addition to the built-in localization engine.

    You can still define your own parser and formatter functions. Our documentation describes all the details, and please let us know via our Support Center if something is missing!

    Intl localization improvements

    Restrictions related to localization using the DevExtreme Intl integration are removed in v17.2:

    • It is not necessary to define a parser manually for any format (this was previously required for the DateBox and for date/time editing in the Data Grid). The correct parser is now generated automatically.

    • Custom format strings are available, as detailed above. Correct month names, decimal and thousands separators are automatically selected for the active locale. This type of custom formatting wasn’t previously supported when using Intl.

    Intl localization functionality is now much closer to that of Globalize. Intl is easier to use, requiring only one external file instead of the many CLDR data files that Globalize requires.

    TextBox mask improvements

    During data entry, it is inconvenient to have to navigate the input caret using the cursor keys, especially when masks are being used. We have improved the default caret behavior:

    • If the current value is undefined and the TextBox isn’t focused, the caret will be set at the beginning of the input when you tap or click any part of the TextBox.

    • If the current value is defined and the TextBox isn’t focused, the caret is set at the end of the input when you tap or click any part of the TextBox.

    • If the TextBox is focused, the caret moves to the position where you tap or click it.

    TextBox Mask improvements

    A new mode has also been added to make the mask visible. The mask can always be displayed, or it can be shown only when the TextBox has been focused.

    TextBox showMaskMode

    Try it!

    Version v17.2.3 is now available. Please visit the DevExtreme site for all the details.

    Please let us know your feedback on the new features!

  • Improvements to DevExtreme HTML5 Chart Date/Time Axis (v17.2)

    This post covers the DevExtreme Chart widget, which is available for jQuery, as an Angular component, ASP.NET MVC and ASP.NET Core MVC controls, and as a Knockout binding.

    Date/Time Series Improvements

    The date/time axis has been one of the weak points of the otherwise robust DevExtreme Chart control. Some customers reported issues with the generation of tick marks at the correct intervals, or with the formatting of tick labels. It was time for us to re-evaluate and improve our implementation, and we have now completed this work for v17.2.

    Tick Mark Generation

    Until now, the tick mark generation mechanism for date/time-scales was inherited from the numeric scale, which turned out to be a terrible idea. Axis label intervals were calculated in milliseconds, producing ticks in awkward positions, for instance at 29 days and 12 hours instead of 1 month, or at 6 days instead of a week.

    Now the tick interval is calculated so that labels always show the start of reasonable date/time intervals: the first day of a week, month or year, the start of a day, the top of an hour, etc.

    Intelligent tick intervals

    Axis Auto-Formatting

    Before v17.2, Axis labels were generated in a straightforward manner similar to tick marks, using a single format for all of them. As a result, there were few tick labels with long text.

    Now, the dxChart widget carefully chooses an axis label format for each label individually.

    Date/time label formatting

    Label auto-formatting is used in numeric scales, too, in which case the widget chooses one of the “large number” formats. In addition, you can set up a numeric axis to show integer values exclusively.

    Numeric scale label auto-formatting

    Weekend Skipping

    If your dataset contains entries for workdays only, you may want to exclude weekends and holidays from the axis. This is now possible using the options holidays and workWeek (optionally) and then setting workdaysOnly to true:

      argumentAxis: {
        // specify holidays to exclude
        holidays: [
          new Date(2017, 11, 25),
          new Date(2017, 11, 26)
        // specify which days are workdays (skipping Mondays in this example):
        workWeek: [2, 3, 4, 5],
        // activate the skipping:
        workdaysOnly: true

    Weekend skipping

    Try it

    A beta of v17.2 is available right now via npm:

    npm i devextreme@17.2.2-pre-beta

    Please let us know your thoughts about these new features!

  • Pyramid Charts with the DevExtreme HTML5 Funnel Chart Widget (v17.2)

    This post covers the DevExtreme Funnel Chart widget, which is available for jQuery, as an Angular component, ASP.NET MVC and ASP.NET Core MVC controls, and as a Knockout binding.

    The Funnel Chart widget can be used to display pyramid charts as well as funnel charts (which have previously been described in this blog post). A pyramid chart is an isosceles triangle (meaning it has two sides of equal length) divided into sections. These sections are ordered by importance, which allows pyramid charts to be used to visualize hierarchies. The height of each section indicates quantity.

    How to use a Pyramid Chart

    Perhaps the most common example of a pyramid chart is Maslow’s hierarchy of needs. This pyramid arranges human needs from the most fundamental, such as food, water and rest, at the base to comparatively less essential, like fullfilling one’s potential, at the top. We created this chart using the new DevExtreme Funnel Chart widget available in the upcoming v17.2 release.

    Maslow's hierarchy of needs

    A pyramid chart has many applications besides Maslow’s hierarchy. Visualizing the organizational structure of a company is one of them. Executives appear at the top of the pyramid, above middle management, and lower-ranking employees are shown at the bottom. The chart reflects both the power structure in the company and the relative size of each group.

    Organization structure

    In the following example, a pyramid chart is used to analyze sales in a bike shop. In this case, the hierarchy indicates a priority of the goods sold by the shop, perhaps an advertising priority or a shipping priority. From this chart, you can see that clothing sells almost as well as bikes, which are presumably the “main” article, since they are shown at the pyramid base. Increasing the supply of clothing might add to the revenue.


    Try it

    A beta of v17.2 is available right now via npm:

    npm i devextreme@17.2.2-pre-beta

    Use the following code to create a simple pyramid chart:

      dataSource: [ 
        { item: "Lower-ranking Employees", count: 200 }, 
        { item: "Middle Management", count: 150 }, 
        { item: "Executives", count: 30 } 
      title: "Organization Structure", 
      sortData: false, 
      argumentField: "item", 
      valueField: "count", 
      algorithm: "dynamicHeight", 
      inverted: true 

    Please let us know your thoughts about this use case!

  • What's New in the Data Grid for React (Beta)

    The first Beta version of the DevExtreme React Grid is now available!

    We have already talked about some new features of the React Grid in our recent blog posts. If you’ve missed them, you can follow these links to read about the Material Design integration and some new capabilities for data processing customization. In this post I’ll sum up other improvements that we’ve made between the very first CTP release and the Beta. In this post I’ll be using the Bootstrap version for the visual examples.

    Paging control improvements

    Page size selector

    We have introduced a page size selector control that appears in the Grid footer side by side with the page switcher. It allows the user to change the number of rows visible on a single page. It also can be configured to contain an ‘All Rows’ item to show all rows at once.

    Please refer to the data paging guide for demos and more details.

    Page size selector

    Responsive mobile-friendly paging panel

    Mobile devices have become the primary channel for consuming digital information and working with data online. To provide the best possible experience on such devices, we have made the React Grid paging controls responsive and usable on small screen sizes.

    Mobile pager

    New configuration features for end users

    Column reordering and resizing

    Our React Data Grid allows the end user to configure many aspects of structural data appearance: sorting, grouping and others. Since the very first release we’ve introduced column resizing and column reordering functionality.

    Please refer to the column reordering and column resizing guides for demos and more details.

    Reordering and resizing

    Configuration via Drag-and-Drop

    Some end user configuration tasks can naturally be performed via drag-and-drop. For instance, an end user might want to change the column order by dragging a column to the desired position. We have introduced this functionality recently: now it’s possible to reorder columns by drag-and-drop, and to change column sizes by dragging a column’s resizing grip (see the screencast above this paragraph). It is now also possible to group and ungroup fields by dragging and dropping a column header to or from the Grid grouping panel. This capability is optional, and it is possible to disable drag-and-drop customization, and to enable column grouping buttons instead or in addition.

    Drag and drop

    Column chooser

    In a real-world web application data structures are often complex, with large numbers of properties, resulting in large numbers of Grid columns. End users may need to see only certain subsets of all available columns for specific use cases. The ColumnChooser component allows the user to set up the visible columns. It works with the TableColumnVisibility React Grid plugin. You have full control over the column chooser, and where or when to make it visible within your app. You can also control Grid column visibility without using the column chooser, perhaps with the help of your own custom UI component. Please refer to the Controlling Column Visibility guide for demos and more details.

    Column chooser

    Cancel column sorting with the Ctrl or Command key

    A minor but important improvement: sorting can be canceled for a specific column by clicking its header cell with the Ctrl key pressed (Command on Mac).

    Virtual Scrolling in React Grid for Material UI

    Before the React Grid Beta release, the virtual scrolling feature was only available for the Bootstrap grid. We can now announce that virtual scrolling is supported for Material UI. Hundreds of thousands of records can be shown without pagination.

    Try it yourself in our demo (switch to Material UI).


    All built-in React Data Grid text resources are now localizable via the messages properties on the plugins. It’s also possible to configure data formatting with the help of the DataTypeProvider plugin. That means you can use any localization library you like, or the built-in Intl localization capabilities of the browser.

    Please refer to the localization and data types guides for demos and more details.


    Accessibility and other improvements

    We have spent some time making the Grid more accessible. The first step is keyboard navigation. It is now possible to work with the Grid, in a desktop scenario, without using a mouse. We also plan to support the WIA-ARIA standard in future releases.

    You might find other minor improvements in our Grid for React that are not mentioned in this post.

    Feel free to download your copy from npm and let us know what you think. Your feedback is highly appreciated and will help us ship a stable RTM release without bugs or API inconveniences, as soon as possible.

  • XPO for .NET Core (.NET Standard 2.0, Beta in v17.2)

    Ever since .NET Core was first released, we have had requests to support XPO, our object/relational mapping solution, on the platform. Today I can finally announce that support is available – .NET Standard 2.0 made it possible!

    Getting started

    We have added a special page for .NET Core to our product documentation, which you can find by following this link. You’ll see that XPO can be added to your project as a NuGet package with a simple command:

    dotnet add package DevExpress.Xpo -v 17.2.2-beta -s https://nuget.devexpress.com/early-access/api

    The special URL you see, with early-access in it, can be used by all during the current beta phase. If you have a personal key for our NuGet repository (all about that here), you can replace the early-access part with that key, or omit the -s parameter entirely if you have NuGet configured already on your system.

    Once the package is installed, I recommend you have a look at the special .NET Standard 2.0 demos we have created. Of course the XPO API remains the same! You can apply all the information from our tutorials and examples, and even the overview I gave in my XPO webinar still applies for most of its content.

    On November 21st, we offer a webinar about XPO on .NET Core. Here’s our list of webinars, where you can sign up for this event.


    Even though .NET Standard 2.0 has come a long way and added lots of APIs that were previously missing from .NET Core, there are still a few pieces of XPO functionality that aren’t supported due to platform restrictions. Here’s a list that I believe to be complete at this time:

    1 – Providers: The full list of XPO supported database systems will be updated soon. At this time, XPO on .NET Core supports SQL Server, MySql, PostgreSQL and SQLite. Note that this is not really an XPO limitation – as soon as RDBMS vendors begin supporting .NET Standard 2.0, we will test XPO with those RDBMS providers and add them to our supported list.

    2 – OData: OData Services are not supported because our existing implementation relies on the Microsoft.Data.Services library, which only supports the .NET Framework.

    3 – The WCF based IDataStore implementations DataStoreService and CachedDataStoreService are technically available, but you won’t be able to run an application that uses them on .NET Core because it lacks the ServiceHost class. However, the related DataStoreClient and CachedDataStoreClient can be used, for instance in a Xamarin app, to access XPO services hosted on full .NET.

    4 –  The visual designer should not be used at this time, because it adds references to “standard” XPO into your project. Of course it is possible to use designer-generated classes, for instance by copying them from another project.
    NOTE: This limitation exists only in v17.2.2. Version 17.2.3+ already supports the visual designer in .NET Standard 2.0 projects. 

    Try it!

    If you use .NET Core, or consider doing so, please give XPO a spin! We are very interested in your feedback or questions!

    Finally, we are still interested in feedback through our survey about ORM and .NET Core!

  • DevExtreme HTML5 Pivot Grid Remote Data Processing

    This post covers the DevExtreme Pivot Grid widget, which is available for jQuery, as an Angular component, ASP.NET MVC and ASP.NET Core MVC controls, and as a Knockout binding.

    In the past (prior to v16.2), a connection to an OLAP cube (an XMLA store) was the only way to use the Pivot Grid with large data sources. Configuration and use of OLAP cubes are complicated, and client-side data processing can’t easily be applied because of the limited memory and performance available to browser runtimes as well as the simple fact that large data volumes would need to be transferred to the client in the first place. Server side data aggregation without an OLAP cube is the technique of choice for this scenario.

    Pivot Grid Remote Data

    Starting with DevExtreme v16.2, you can connect the Pivot Grid to a relational data source in server mode to perform filtering, grouping and summary calculation operations on the server without using OLAP or Analytic services.

    If you enable server mode by assigning true to the remoteOperations option, the Pivot Grid sends filtering, grouping and summary calculation options to the server and waits for the processed data.

    Comparing performance

    We compared loading time and network traffic volume when processing data locally and remotely. Here’s what we did, in case you would like to reproduce our tests.

    We created a database with the following table:

    CREATE TABLE [dbo].[Categories] (
      [CategoryID] INT IDENTITY (1, 1) NOT NULL,
      [CategoryName] VARCHAR (10) NULL,
      [RegisterDate] DATETIME NOT NULL,
      [Count] INT NOT NULL,
      [Price] DECIMAL (18, 2) NOT NULL,
      CONSTRAINT [PK_dbo.Categories] PRIMARY KEY CLUSTERED ([CategoryID] ASC)

    We added the following indices to the table to optimize server-side grouping:

    CREATE INDEX CategoryIndex [dbo].[Categories] (CategoryName);
    CREATE INDEX DateIndex [dbo].[Categories] (RegisterDate);

    We fill the table with random data, including 100 unique CategoryName values and a RegisterDate range of three years.

    We configured the Pivot Grid like this:

      dataSource: {
        fields: [
          { dataField: "RegisterDate", dataType: "date", area: "column" },
          { dataField: "CategoryName", area: "row" },
          { dataField: "Price", summaryType: "sum", area: "data", 
            format: { type: "currency" } }

    When measuring performance, we used the DevExtreme.AspNet.Data library to process data on the server. Below are a comparison table and charts showing the results.

    Comparison table

    Comparison charts

    As you can see, client-side processing slows down dramatically with increasing record count, and becomes quite unusable with data sets of one million records. Remote data processing works fine even if the record count is 3 million. Note also how the data transfer volume remains almost constant for remote operations, while it obviously increases quickly for local operations. Of course, the Pivot Grid in server mode can process data sets containing many more than 3 million records, with loading time depending only on database configuration and server performance.

    Try it!

    We have published a sample that demonstrates how to configure the Pivot Grid widget to work with a remote WebAPI data service. Additionally, there is the DevExtreme PHP Data Library, which allows you to use the Pivot Grid Remote Data Processing feature with a mysql database and a PHP server. Finally, it is possible to run a JavaScript based server accessing a MongoDB database using this library.

    We maintain a list of links to samples in the devextreme-examples GitHub repository.

    Please let us know your thoughts about this feature and our results!

  • Custom Sorting, Grouping, Filtering and More in DevExtreme Grid for React

    We have received a lot of valuable feedback from users of our React Grid alpha versions. Many thanks to everybody! Some of the feedback has already been used as a basis for enhancements to the component. I should mention that we tend not to extend the Grid as a “black box” with lots of built-in features. Usually, we just provide customization capabilities to implement new features on top of our React Grid. Mostly we make API improvements that allow a developer to customize grid behavior and appearance by replacing some of its core algorithms or UI templates. Here is an overview of some recent changes.

    Custom Sorting, Grouping, Filtering and More

    Custom data accessors

    Document-based NoSQL databases are getting more and more popular, which means the data from the server is not flat and tabular, but has complex structures involving nested objects and arrays. It is inconvenient to flatten the data every time it’s obtained from the server, before passing it to the Grid, and a flattening step makes it more complicated to send modified data back to the server. To display nested or computed data, you can now specify a getCellValue function in a column configuration object:

    const rows = [
      { user: { firstName: 'John', lastName: 'Smith' } }
      /* ... */
    const columns = [
        name: 'firstName',
        title: 'First Name',
        getCellValue: row => (row.user ? row.user.firstName : undefined)
        name: 'lastName',
        title: 'Last Name',
        getCellValue: row => (row.user ? row.user.lastName : undefined)
      /* ... */
    /* ... */

    If your data grid is editable, you also need a way to pass cell changes back to the row object. We introduced a createRowChange function, which accepts the whole row and the new cell value as parameters, and should return a “row change” object that reflects changes made to the row. Note that the original row should be regarded immutable, so we create and return a new object with the modified fields. This change is merged into the changedRows state via the EditingState plugin.

    const rows = [
      { user: { firstName: 'John', lastName: 'Smith' } }
      /* ... */
    const columns = [
        name: 'firstName',
        title: 'First Name',
        getCellValue: row => (row.user ? row.user.firstName : undefined),
        createRowChange: (row, value) => ({
          user: {
            firstName: value,
      /* ... */

    Please refer to the data accessors guide for demos and more details.

    Formatters and editors for custom data types

    Now you can define any custom data type and specify how a value of this type should be displayed and edited. This capability is provided by the DataTypeProvider plugin. All you need to do is to add a dataType to the column configuration object and set up formatterTemplate and editorTemplate properties for the DataTypeProvider, which will be used to show or edit the column value:

    const rows = [
      { product: 'SolarOne', price: '3039' }
    const columns = [
      { name: 'product', title: 'Product' },
      { name: 'amount', title: 'Sale Amount', dataType: 'currency' }
        formatterTemplate={({ value }) => <span>${value}</span>}
        editorTemplate={({ value, onValueChange }) => (
              onChange={e => onValueChange(Number(e.target.value))}

    Please refer to the data types guide for demos and more details.

    Custom filtering predicates

    The default React Grid filtering predicate uses a case-insensitive “contains” algorithm. Now you can specify custom filtering predicates using the getColumnPredicate property on the LocalFiltering plugin. If the getColumnPredicate function returns undefined for a column, the default filtering predicate is used.

    const startsWithPredicate = (value, filter) => 
    const getColumnPredicate = columnName => {
      if (columnName === 'city') {
        return startsWithPredicate;
      <FilteringState />
      <LocalFiltering getColumnPredicate={getColumnPredicate} />
      <TableView />
      <TableHeaderRow />
      <TableFilterRow />

    Please refer to the filtering guide for demos and more details.

    Custom sorting compare functions

    In some scenarios, custom sorting algorithms are required. For instance, you might have an enumeration value represented by its ID in your database. Imagine a ‘priority’ column with valid values “Low”, “Normal” and “High”. You would want this column to be sorted by the underlying numeric values, not alphabetically. The getColumnCompare property of the LocalSorting plugin allows you to implement this scenario.

    Note that the comparison function is expected to implement a three-way comparison. For brevity, the following example uses a simple method of calculating a result for numeric values.

    const priorityWeights = {
      Low: 0,
      Normal: 1,
      High: 2
    const comparePriority = (valA, valB) => 
      priorityWeights[valB] - priorityWeights[valA];
    const getColumnCompare = columnName => {
      if (columnName === 'priority') {
        return comparePriority;
      <SortingState />
      <TableView />
      <TableHeaderRow allowSorting />

    If the getColumnCompare function returns undefined, it applies the default sorting algorithm.

    Please refer to the sorting guide for demos and more details.

    Custom grouping values

    Data grouping is a powerful feature that helps visualize and analyze large numbers of rows. Usually, a particular row is classified to belong to a specific group by its exact column value. For instance, two rows can belong to one group if they have equal values for the ‘city’ column. Sometimes, your application requires data grouping to use more complex algorithms for row classification.

    One common scenario is to group items by only the first character of a string property. For instance, you might need to group people by the first characters of their last names. Another use case is to group orders by year, month, day, or other custom intervals. Our Grid provides the capability to perform these kinds of custom groupings by implementing the getColumnIdentity property of the LocalGrouping plugin:

    const byFirstLetter = value => ({
      key: value.substr(0, 1)
    const getColumnIdentity = (columnName) => {
      if (columnName === 'city') {
        return byFirstLetter;
      <GroupingState />
      <LocalGrouping getColumnIdentity={getColumnIdentity} />
      <TableView />
      <TableHeaderRow />
      <TableGroupRow />

    Please refer to the grouping guide for demos and more details.

    Remote and custom local grouping

    In some cases, your data might be grouped already. For instance, the data may have been obtained from a server that supports grouping itself. You would like to pass this data to the Grid “as is”, while retaining the standard grouping UI with its interactive group expanding/collapsing features. The new CustomGrouping plugin has been introduced for this purpose. You need to configure it to describe your data structure and then pass the grouped data to the grid.

    const columns = columns: [
      { name: 'name', title: 'Name' },
      { name: 'sex', title: 'Sex' },
    const groupedData = [{
      key: 'Male',
      items: [
        { id: 1, name: 'Paul', sex: 'Male' },
        { id: 2, name: 'John', sex: 'Male' },
    }, {
      key: 'Female',
      items: [
        { id: 3, name: 'Jane', sex: 'Female' },
        { id: 4, name: 'Kate', sex: 'Female' },
    const getChildGroups = groups => groups
      .map(group => ({ key: group.key, childRows: group.items }));
    const grouping = [{ columnName: 'sex' }];
    <Grid rows={groupedData} columns={columns}>
      <GroupingState grouping={grouping} />
      <CustomGrouping getChildGroups={getChildGroups} />
      <TableView />
      <TableHeaderRow />
      <TableGroupRow />

    Please refer to the custom grouping and remote grouping guides for demos and more details.

    UI customization via templates

    To render individual UI elements, our React Grid uses templates that are passed via props to the Grid’s UI plugins. This happens automatically and internally, so you don’t normally see these templates specified anywhere. A template is a function that returns a React Element depending on the arguments it receives. If you need to modify the default appearance or behavior you can replace default templates with custom ones using template properties on the various plugins.

    const customRowTemplate = ({ children, row }) => (
      <tr onClick={() => alert(row.id)}>
      <TableView tableRowTemplate={customRowTemplate} />
      <TableHeaderRow />

    Please refer to the appearance customization guide for demos and more details. This approach is applicable to both the Bootstrap React Grid and the React Grid for Material Design.

    Feel free to download your copy from npm and let us know what you think.

  • React Data Grid for Google Material Design

    Material-UI (the Material Design React component library) version 1.0 is about to release, and so is our DevExtreme React Grid v1.0 (at the same time as DevExtreme v17.2). The very first pull request that started our work on Material UI integration was merged four months ago. Since then, our Material UI data grid has caught up to its Bootstrap counterpart. In this post I’d like to sum up what has been done to support the Google Material Design Data Table in the DevExtreme React Grid.

    React Grid Material UI

    Editing UI

    Editing is one of the most demanded features of any data grid. It allows users to create, update and delete rows right in the visual data table. To provide this functionality, the React Grid renders specific editing controls if the editing-related plugins are used. You can customize the appearance of editing controls. For instance, you can specify the text and icons you want to see in your application, or provide custom value editors for certain columns.

    Read our React Grid docs about editing (they apply for Bootstrap and Material UI)

    Editing UI

    Filtering UI

    A typical real-world LOB application visualizes and manages a lot of data. Search capabilities are crucial to the end-user experience. Our Material UI data grid has a set of plugins that implement filtering functionality, such as the Filter Row, special row shown right underneath the table header, containing filter editors used to enter filter values.

    Read our React Grid docs about filtering (they apply for Bootstrap and Material UI)

    Filtering UI

    Grouping UI

    Another technique that simplifies work with large amount of data is to group information by criteria. End users can browse grouped rows and expand or collapse them as needed. The Google Material Design guidelines don’t contain specifications for a data table grouping UI. We did our best to provide UI for this feature that would be consistent with the guideline intentions. Multi-level grouping by several columns or custom values is also available.

    Read our React Grid docs about grouping (they apply for Bootstrap and Material UI)

    Grouping UI

    Paging UI

    Row paging is a must-have common feature that is expected by almost every data grid user. As you would expect, the Google Material Design guidelines contain specifications for this feature and we observe them in our Material UI Data Grid for React. The Grid provides controls to change page size, switch the current page and to display the number of available pages as well as the range of visible rows. Paging is integrated with the Grouping feature, so the Grid shows the current page group header on each page, if grouping is configured.

    Read our React Grid docs about paging (they apply for Bootstrap and Material UI)

    Paging UI

    Selection UI

    In web applications that allow data manipulation, you usually need row selection capabilities. An end-user might want to delete rows or perform batch updates, for which rows need to be selectable. Selections can incorporate individual rows, all rows on the current page, or all rows loaded in the Grid. The appearance of row selection in data tables is specified in the Material Design guidelines and we have implemented it for the DevExtreme React Grid accordingly.

    Read our React Grid docs about selection (they apply for Bootstrap and Material UI)

    Selection UI

    Row Detail UI

    When your data row is represented as a complex structure, the Detail Row feature can be very helpful. It allows the Grid to display many rows in a compact view when collapsed, but end users can expand individual rows as required to display row details. You can also implement master/detail scenarios using the Detail Row feature.

    Read our React Grid docs about row details (they apply for Bootstrap and Material UI)

    Row Details UI

    Light, Dark and Custom Material Design Themes

    There are two standard Material Design themes: Light and Dark. They are both supported by the React Data Grid for Material UI. If you don’t like these standard themes you can configure your own, for instance to reflect the colors of your company branding.

    See our React Grid theming demos (switch to Material UI)

    Dark Material Design Theme

    Lots of other features

    In time for our final release we expect all other React Grid features supported by the Bootstrap Grid to be available for Material Design as well. Sorting, column reordering, column resizing, the column chooser and others are available now, while virtual scrolling for Material UI will be implemented soon.

    Other features

    Feel free to download your copy from npm and let us know what you think!

2 3 4 5 6 7

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383


DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2018 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners