Tables are one of the easiest ways to present data on web pages. Plain HTML tables can meet the basic data presentation needs, but trying to squeeze anything sophisticated from them will quickly make you frustrated.

This is when you need to make some important decisions about your application development path. You can start coding enhancements around old-fashioned HTML tables — at the risk of losing focus on your project — or you look at the existing products that are designed to solve your problems.

Today’s market offers dedicated smart table controls that handle the table part for you and provide additional features, including selection modes, sorting, and column reordering.

Many companies use data tables to show complex reports, dashboards, financial data, sales results, and even interactive spreadsheets. High demand begot specialized supply, so tables are well represented in web component libraries.

In this article, we'll discuss which capabilities are expected from a smart table, assess a few open-source alternatives, and demonstrate how to create superior HTML smart data tables with GrapeCity's solution for the React JavaScript library. We are assuming that you have some web development experience and preferably familiarity with React.

Try SpreadJS's spreadsheet components

Download the latest version of SpreadJS

Download Now!

Table Capabilities

There are some key features that people expect from a smart data table.

  • Data features:

    • Load data from the various sources, including local files, databases, and APIs
    • Searching, filtering, and sorting options
    • Load and display of large datasets with pagination
    • Ability to import and export data
  • UI features:

    • Showing and hiding columns
    • Inline editing
    • Responsiveness — built-in support for multiple devices
    • Resizable columns to accommodate long data points inside a column (multi-line comments)
    • Horizontal and vertical scroll support
    • Data validations and visualizations, such as sparklines

Modern frameworks have built-in implementations of some of these features. However, you have to code more advanced features yourself.

Open Source Frameworks

Created and maintained by Facebook, React is a massively popular open-source JavaScript library. Currently, it holds around 60% of the JavaScript framework market share. With such widespread adoption in the industry, it’s no wonder that many products have been created to serve applications built on React.

Here are some popular open-source smart data table libraries made for React:

These open-source projects have advantages and disadvantages. Depending on which feature you are looking for, some of these components are better than others.

Create a React App with React Data Grid

Let’s build a new Node-based, React application with React Data Grid, an open-source component that has a look-and-feel close to what we are trying to demonstrate.

Install Node.js. Then, using a command-line console, create a new Node React app:

npx create-react-app my-app  
cd my-app  
npm start

Install the React Data Grid package. Open the package.json file and add these lines in the dependencies section:

"babel-loader": "^8.1.0",  
"react-data-grid": "5.0.1",  
"react-data-grid-addons": "5.0.4",  
"bootstrap": "^4.5.2"

append the following lines after the browserslist section:

"devDependencies": {  
  "immutable": "^4.0.0-rc.12"  
}

To install the React Data Grid package and its dependencies, run the npm install command-line instruction:

npm install

Add a new data folder under the src folder, and create a new file named data.js. The user will use the data to populate our data grid:

export const recentSales = [  
  {  
    id: 1,  
    country: "Canada",  
    soldBy: "Bill",  
    client: "Cerberus Corp.",  
    description: "Prothean artifacts",  
    value: 6250,  
    itemCount: 50  
  },  
  {  
    id: 2,  
    country: "Canada",  
    soldBy: "Bill",  
    client: "Strickland Propane",  
    description: "Propane and propane accessories",  
    value: 2265,  
    itemCount: 20  
  },  
  {  
    id: 3,  
    country: "USA",  
    soldBy: "Ted",  
    client: "Dunder Mifflin",  
    description: "Assorted paper-making supplies",  
    value: 4700,  
    itemCount: 10  
  },  
  {  
    id: 4,  
    country: "USA",  
    soldBy: "Ted",  
    client: "Utopia Planitia Shipyards",  
    description: "Dilithium, duranium, assorted shipbuilding supplies",  
    value: 21750,  
    itemCount: 250  
  },  
  {  
    id: 5,  
    country: "USA",  
    soldBy: "Ted",  
    client: "Glengarry Estates",  
    description: "Desks, phones, coffee, steak knives, and one Cadillac",  
    value: 5000,  
    itemCount: 5  
  },  
  {  
    id: 6,  
    country: "Germany",  
    soldBy: "Angela",  
    client: "Wayne Enterprises",  
    description: "Suit armor and run-flat tires",  
    value: 35000,  
    itemCount: 25  
  },  
  {  
    id: 7,  
    country: "Germany",  
    soldBy: "Angela",  
    client: "Stark Industries",  
    description: "Armor and rocket fuel",  
    value: 25000,  
    itemCount: 10  
  },  
  {  
    id: 8,  
    country: "Germany",  
    soldBy: "Angela",  
    client: "Nakatomi Trading Corp.",  
    description: "Fire extinguishers and replacement windows",  
    value: 15000,  
    itemCount: 50  
  },  
  {  
    id: 9,  
    country: "UK",  
    soldBy: "Jill",  
    client: "Spaceley Sprockets",  
    description: "Anti-gravity propulsion units",  
    value: 25250,  
    itemCount: 50  
  },  
  {  
    id: 10,  
    country: "UK",  
    soldBy: "Jill",  
    client: "General Products",  
    description: "Ion engines",  
    value: 33200,  
    itemCount: 40  
  }  
];

Add a new components folder under the src folder, and create a new file named OpenSourceTable-Demo.js:

/my-app  
  /src  
    /components  
      OpenSourceTable-Demo.js

Open the OpenSourceTable-Demo.js file and add the following code. (Here, we import the ReactDataGrid component and declare the React state variables that will be used by the data grid as column definitions and the component’s data source):

import 'bootstrap/dist/css/bootstrap.min.css';  
import React, { useState } from 'react';  
import ReactDOM from "react-dom";  
import ReactDataGrid from "react-data-grid";  
import { recentSales } from "../data/data";

export const OpenSourceTableDemo = () => {

  const [columns, setColumns] = new useState([  
    { key: "id", name: "Id" },  
    { key: "country", name: "Country" },  
    { key: "soldBy", name: "Sold by" },  
    { key: "client", name: "Client" },  
    { key: "description", name: "Description" },  
    { key: "value", name: "Value" },  
    { key: "itemCount", name: "Item Count" }  
  ]);

  const [sales, setSales] = new useState(recentSales);  
}

Modify the OpenSourceTableDemo component so that it returns the HTML with the ReactDataGrid component:

return (  
  <div className="card main-panel">  
    <div className="card-header">  
      <h1>Open Source</h1>  
    </div>  
    <div className="card-body">  
    <h5>React Data Grid Demo</h5>  
      <p>  
        Building a Smart Data Table in React with React Data Grid  
      </p>           
      <div className="container-fluid">  
        <div className="row">  
            <ReactDataGrid  
                columns={columns}  
                rowGetter={i => sales[i]}  
                rowsCount={recentSales.length}  
              />  
        </div>  
      </div>  
    </div>  
  </div>);

Edit the App.js file and replace its contents with the lines below:

import React from 'react';  
import './App.css';  
import { OpenSourceTableDemo } from './components/OpenSourceTable-Demo.js'

function App() {  
  return (  
    <OpenSourceTableDemo/>  
  );  
}

export default App;

Now run the app:

npm start

Once the app is running, you’ll see the React Data Grid displaying the sales data:

ReactDataGrid

To show some of the component features, let’s start customizing our open-source data grid to support cell value updates, row sorting, and column reordering.

Implement Cell Value Update

Open the OpenSourceTable-Demo.js file and add the editable: true attribute to each of the grid column definitions:

{ key: "id", name: "Id", editable: true },  
{ key: "country", name: "Country", editable: true },  
{ key: "soldBy", name: "Sold by", editable: true },  
{ key: "client", name: "Client", editable: true },  
{ key: "description", name: "Description", editable: true },  
{ key: "value", name: "Value", editable: true },  
{ key: "itemCount", name: "Item Count", editable: true }

Add a new onGridRowsUpdated function to handle cell updates and update the underlying data source:

  const onGridRowsUpdated = ({ fromRow, toRow, updated }) => {  
    const s = sales.slice();  
    for (let i = fromRow; i <= toRow; i++) {  
      s[i] = { ...s[i], ...updated };  
    }  
    setSales(s);  
  };

Modify the ReactDataGrid component to add the enableCellSelect={true} attribute and an onGridRowsUpdated={onGridRowsUpdated} event handler:

<ReactDataGrid  
  columns={columns}  
  rowGetter={i => sales[i]}  
  rowsCount={recentSales.length}  
  enableCellSelect={true}  
  onGridRowsUpdated={onGridRowsUpdated}  
/>

These changes allow your React Data Grid to handle updates and persist them in the underlying data source:

ReactDataGrid

Implement Row Sorting

Open the OpenSourceTable-Demo.js file and add the sortable: true attribute to each column definition to enable column sortability:

{ key: "id", name: "Id", editable: true, sortable: true },  
{ key: "country", name: "Country", editable: true, sortable: true },  
{ key: "soldBy", name: "Sold by", editable: true, sortable: true },  
{ key: "client", name: "Client", editable: true, sortable: true },  
{ key: "description", name: "Description", editable: true, sortable: true },  
{ key: "value", name: "Value", editable: true, sortable: true },  
{ key: "itemCount", name: "Item Count", editable: true, sortable: true }

Implement the new sortRows function:

  const sortRows = (initialRows, sortColumn, sortDirection) => rows => {  
    const comparer = (a, b) => {  
      if (sortDirection === "ASC") {  
        return a[sortColumn] > b[sortColumn] ? 1 : -1;  
      } else if (sortDirection === "DESC") {  
        return a[sortColumn] < b[sortColumn] ? 1 : -1;  
      }  
    };  
    return sortDirection === "NONE" ? initialRows : [...rows].sort(comparer);  
  };

Modify the ReactDataGrid component to implement the onGridSort event handler and reference the function we have just created:

<ReactDataGrid  
  columns={columns}  
  rowGetter={i => sales[i]}  
  rowsCount={recentSales.length}  
  enableCellSelect={true}  
  onGridRowsUpdated={onGridRowsUpdated}  
  onGridSort={(sortColumn, sortDirection) =>  
      setSales(sortRows(sales, sortColumn, sortDirection))  
  }  
/>

Go back to the web page and notice how the columns are now sortable:

ReactDataGrid

Implement Column Reordering

Open the OpenSourceTable-Demo.js file and add this declaration after the imports section:

const {  
  DraggableHeader: { DraggableContainer }  
} = require("react-data-grid-addons");

Add the draggable: true property to each column definition to enable column repositioning:

{ key: "id", name: "Id", editable: true, sortable: true, draggable: true },  
{ key: "country", name: "Country", editable: true, sortable: true, draggable: true },  
{ key: "soldBy", name: "Sold by", editable: true, sortable: true, draggable: true },  
{ key: "client", name: "Client", editable: true, sortable: true, draggable: true },  
{ key: "description", name: "Description", editable: true, sortable: true, draggable: true },  
{ key: "value", name: "Value", editable: true, sortable: true, draggable: true },  
{ key: "itemCount", name: "Item Count", editable: true, sortable: true, draggable: true }

Add the onHeaderDrop function to handle column drag-and-drop event:

const onHeaderDrop = (source, target) => {  
  var columnsCopy = columns.slice();  
  const columnSourceIndex = columns.findIndex(  
    i => i.key === source  
  );  
  const columnTargetIndex = columns.findIndex(  
    i => i.key === target  
  );

  columnsCopy.splice(  
    columnTargetIndex,  
    0,  
    columnsCopy.splice(columnSourceIndex, 1)[0]  
  );

  setColumns(columnsCopy.splice());  
  setColumns(columnsCopy);  
};

Wrap your existing ReactDataGrid component inside a new DraggableContainer component:

  <DraggableContainer onHeaderDrop={onHeaderDrop}>  
      <ReactDataGrid  
            columns={columns}  
            rowGetter={i => sales[i]}  
            rowsCount={recentSales.length}  
            enableCellSelect={true}  
            onGridRowsUpdated={onGridRowsUpdated}  
            onGridSort={(sortColumn, sortDirection) =>  
              setSales(sortRows(sales, sortColumn, sortDirection))  
            }  
        />  
  </DraggableContainer>

Rerun the app and try moving the grid columns around:

ReactDataGrid

That looks pretty good, but it was a lot of work to implement those features. Now you're on the hook to maintain that code.

Effective Alternatives

If your company develops first-rate, enterprise-grade applications, you should look into more professional products that offer support for multiple JavaScript frameworks and cover a complete functionality range.

GrapeCity provides several data table products that can be implemented in a React app with a few code lines. These products are packed with a rich set of ready-to-use features that require no customization, unlike the open-source components we’ve discussed above.

Let’s have a look at several lightweight, smart table products provided by GrapeCity, including SpreadJS, DataViewJS, and Wijmo FlexGrid.

SpreadJS

SpreadJS is the World's #1 selling JavaScript Spreadsheet with over 450 Excel functions. Using SpreadJS, you can quickly deliver Excel-like spreadsheet experiences with zero dependencies on Excel, with full support for React, Vue, Angular, and TypeScript.

SpreadJS enables you to create financial reports and dashboards, budgeting and forecasting models, scientific, engineering, healthcare, education, science lab notebooks, and other JavaScript applications for standard spreadsheet scenarios.

For more advanced spreadsheet use cases, SpreadJS allows you to create custom spreadsheets, advanced grids, dashboards, reports, and data input forms with the comprehensive API. Powered by a high-speed calculation engine, SpreadJS enables the most complex calculations.

SpreadJS supports integration by importing and exporting features that work seamlessly with the most demanding Excel.xlsx spreadsheets.

DataViewJS

DataViewJS is a DataGrid platform focused on advanced data presentation. It goes beyond the traditional tabular displays by providing several presentation views, including tree, card, masonry, trellis, timeline, Gantt, calendar, and grid.

With a single line of code, DataViewJS' customization allows you to change layouts freely. It fully supports Angular, React, and Vue.JS.

Wijmo FlexGrid

FlexGrid is one of the Wijmo product family, which also includes JavaScript/HTML5 UI Components such as FlexChart, Input, PivotChart, FinancialChart, ReportViewer, and so on. FlexGrid fully supports Angular, AngularJS, ReactJS, VueJS, and Knockout.

The lightning speed, extensibility, and independence make Wijmo FlexGrid the ultimate JavaScript smart data grid. FlexGrid’s small footprint improves performance and reduces load time by keeping your web applications compact.

You can take advantage of Excel-like features of FlexGrid, such as data aggregation, cell merging, star sizing, and cell freezing. Also, Cell Templates provide limitless templates with support for declarative markup and binding expressions.

All these GrapeCity’s products are lightweight and work with virtualization, meaning they keep running at high performance even when they are connected to massive data sources.

Implement a Smart Data Table

Let’s see how to implement a Wijmo FlexGrid smart data table in the Node app we’ve built previously.

Install the Wijmo package with npm:

npm install @grapecity/wijmo.react.all

Add a new components folder under the src folder, and create a new file named WijmoFlexGrid-Demo.js:

/my-app  
  /src  
    /components  
      WijmoFlexGrid-Demo.js

Open the WijmoFlexGrid-Demo.js file and add the following code. (Here, we import the WijmoFlexGridDemo component and declare the React state variable that will be used by the FlexGrid as the component’s data source):

import '@grapecity/wijmo.styles/wijmo.css';  
import 'bootstrap/dist/css/bootstrap.css';  
import '@grapecity/wijmo.react.grid';  
import React, { useState } from 'react';  
import { FlexGrid, FlexGridColumn } from '@grapecity/wijmo.react.grid';  
import { recentSales } from "../data/data";

export const WijmoFlexGridDemo = () => {

  const [sales, setSales] = new useState(recentSales);

    }

Modify the WijmoFlexGridDemo component so that it returns the HTML with the FlexGrid component:

return (  
    <div className="card main-panel">  
      <div className="card-header">  
          <h1>GrapeCity</h1>  
      </div>  
      <div className="card-body">  
      <h5>Wijmo FlexGrid Demo</h5>  
        <p>  
          Building a Smart Data Table in React  
        </p>           
        <div className="container-fluid">  
          <div className="row">  
            <FlexGrid itemsSource={sales}>  
              <FlexGridColumn width={50} binding='id' header="ID" />  
              <FlexGridColumn width={200} binding='client' header="Client" />  
              <FlexGridColumn width={320} binding='description' header="Description" />  
              <FlexGridColumn width={100} binding='value' header="Value"/>  
              <FlexGridColumn width={100} binding='itemCount' header="Quantity" />  
              <FlexGridColumn width={100} binding='soldBy' header="Sold By" />  
              <FlexGridColumn width={100} binding='country' header="Country" />  
            </FlexGrid>  
          </div>  
        </div>

      </div>  
    </div>);

Edit the App.js file to include the reference to our new WijmoFlexGridDemo component:

import React from 'react';  
import './App.css';  
import { OpenSourceTableDemo } from './components/OpenSourceTable-Demo.js'  
import { WijmoFlexGridDemo } from './components/WijmoFlexGrid-Demo.js'

function App() {  
  return (  
    // <OpenSourceTableDemo/>  
    <WijmoFlexGridDemo/>  
  );  
}

export default App;

Run the app:

npm start

Once the app is running, you’ll see the FlexGrid displaying the sales data:

React Data Grid

Cell editing is an out-of-the-box feature in FlexGrid. You can double-click the cells and start editing in place:

React Data Grid

By default, a FlexGridColumn is editable. But you can disable editing by explicitly defining the isReadOnly property in the FlexGridColumn component:

<FlexGridColumn width={50} binding='id' header="ID" isReadOnly='true' />

Also, by default, every FlexGrid column is sortable in ascending or descending order.

React Data Grid

You can lock column sorting by setting the allowSorting property to “false”:

<FlexGridColumn width={200} binding='client' header="Client" allowSorting={false}/>

FlexGrid comes with the ability to reposition columns out of the box freely:

React Data Grid

You can disable column reordering by setting the FlexGridColumn’s allowDragging property to “false”:

<FlexGridColumn width={200} binding='client' header="Client" allowDragging={false}/>

So all the customizations we need to implement on the open-source React Data Grid control are built-in here.

Import Excel Data

Let’s see how we can import Excel data into our FlexGrid component.

Append the following HTML segment after the card-body div in the render() function:

<div className="card-body">  
  <div className="card-footer">     
      <div className="input-group">  
        <div className="custom-file">  
            <input type="file" id="importFile"/>  
        </div>  
        <div className="input-group-prepend">  
            <input type="button" value="Import"/>  
        </div>  
      </div>  
  </div>

Run the application and notice the import section at the bottom of the page:

React Data Grid

Tell the Import button to import the file into our FlexGrid component. Add the onClick function to the input element and pass the name of the function as “import”:

<input type="button" onClick={load} value="Import"/>

Add a new load function inside the component class. Here, we’ll first obtain the full path of the user selected file:

  var load = () => {  
    let fileInput = document.getElementById("importFile");  
    if (fileInput.files[0]) {

    }  
  }

At this point, we’ll need a reference to the FlexGrid instance. Go back to the component declaration and add an event handler that is triggered when the FlexGrid is initialized:

<FlexGrid itemsSource={sales} initialized={initializeFlexGrid}>

Add a declaration for the flexgrid variable and a new function to set it upon FlexGrid initialization:

  const [flexGrid, setFlexGrid] = useState({});  

  var initializeFlexGrid = (flexGrid) => {  
      setFlexGrid(flexGrid);  
  }

Add an import directive to the Wijmo library that handles Excel file contents:

import * as wjcGridXlsx from "@grapecity/wijmo.grid.xlsx";

Back to the load function, add a call to the loadAsync function of the Wijmo library to load the file’s contents into the FlexGrid:

  var load = () => {  
    let fileInput = document.getElementById("importFile");  
    if (fileInput.files[0]) {  
      wjcGridXlsx.FlexGridXlsxConverter.loadAsync(flexGrid, fileInput.files[0], { includeColumnHeaders: true }, function (workbook) {  
        flexGrid.autoSizeColumns();  
     });  
    }  
  }

The Wijmo.xlsx library depends on a JavaScript zip library to compress files. Let’s install this dependency by running this console command:

npm install jszip --save

Rerun the app and test the import feature.

npm start

Open Excel and create a new Demo.xlsx file with these contents:

React Data Grid

Back in our React app, click Choose File, select the Demo.xlsx location, and click the Import button to see the result:

React Data Grid

Finally, let’s see what’s needed to export data from our FlexGrid to Excel.

Add the following HTML snippet after the Import button code to add the new Export button:

<div className="input-group-append">  
  <input type="button" onClick={save} className="input-group-text" value="Export"/>  
</div>

Note that the onClick event handler is pointing to the save function. Let’s implement this function inside the component class:

  var save = () => {

  }

To export FlexGrid data to an .xlsx file, we need to call the saveAsync function of the FlexGridXlsxConverter class:

  var save = () => {  
    wjcGridXlsx.FlexGridXlsxConverter.saveAsync(flexGrid, {  
        includeColumnHeaders: true,  
        includeCellStyles: false,  
        formatItem: false  
    }, "FlexGrid.xlsx");  
  }

Run the app once again and test the Export button:

React Data Grid

Now you can open the .xlsx file exported by the FlexGrid component:

React Data Grid

The above demo barely scratches the surface of the FlexGrid component. We recommend that you explore the GrapeCity page for the Wijmo family of JavaScript UI Components and Tools for complete documentation, demos, and examples written for Angular, React, and Vue.

Wrapping Up

You can create and use React-based smart data tables in various ways. Some approaches require far more manual work than others, but you can’t tell that until you have already spent enough time trying to use them.

There’s plenty of free and open-source table libraries that might meet your everyday needs. We’ve seen how to implement one of them in this article.

However, when it comes to business and enterprise projects, you as a developer don’t want to be distracted and waste your time developing workarounds, additional features, or configuration. This is why a commercial library component suite like Wijmo ensures a solid return on investment.

Built to be framework-agnostic, Wijmo includes full support for Angular, AngularJS, ReactJS, and VueJS, with the same grid across frameworks. For your organization, this means freedom of choice and the ability to save time and development effort if you decide to migrate to another JavaScript framework.

Try Wijmo's controls

Download the latest version of Wijmo

Download Now!