JavaScript
Article
By Oli Folkerd

Make Dynamic Tables in Seconds from Any JSON Data

By Oli Folkerd

This article was peer reviewed by Stephan Max and Simon Codrington. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

Servants unfolding a table

Standard HTML tables can be great if you are just trying to layout some basic data, but what if you are looking for more from your tables? If you need to fetch your data from an external API, make your table sortable or editable, then you are going to need something that packs a bit more of a punch.

If this sounds familiar, then Tabulator is the library for you. Tabulator is a lightweight jQuery UI plugin designed to make building complex interactive tables a doddle, using only a few lines of JavaScript you can turn almost any data source into a beautifully formatted interactive table.

In this tutorial I will take you through the basics of creating your first Tabulator, then expand on some of the options available to add extra features to your tables.

Building Your First Tabulator

Let’s start off by creating a very simple table.

As Tabulator is a jQuery widget you need to include the jQuery and jQuery UI libraries, either from a local source or a CDN of your choice.

You will need to get yourself a copy of the Tabulator library, which can be cloned from the GitHub repo at https://github.com/olifolkerd/tabulator, and include the tabulator.css and tabulator.js files in your project.

<link rel="stylesheet" href="tabulator.css">
<script type="text/javascript" src="tabulator.js"></script>

Create a <div> element to hold the table:

<div id="example-table"></div>

Let’s turn that element into a Tabulator with some JavaScript:

$("#example-table").tabulator();

And there you have it, a functioning table!

OK, so we aren’t quite there yet. To finish our table we need to define the columns and load some data.

Defining the Columns

To define the layout of the table, we need to provide some information about each of its columns.

We do this by passing a column definition array to the Tabulator constructor. Each object in the array represents a column of the table, and contains its setup parameters:

$("#example-table").tabulator({
  columns:[
    {title:"Name", field:"name", sortable:true, width:200},
    {title:"Progress", field:"progress", sortable:true, sorter:"number"},
    {title:"Gender", field:"gender", sortable:true},
    {title:"Favourite Color", field:"col", sortable:false},
    {title:"Date Of Birth", field:"dob"},
    {title:"Cheese Preference", field:"cheese"},
  ],
});

There are a large number of column parameters available, in this demo we will cover a few of these:

  • titleRequired – The title that will be displayed in the header for the column
  • fieldRequired – The key for the column in the data array
  • align – Text alignment for the column (left|center|right)
  • width – Column width (if not set the system will determine the best fit)
  • sortable – Toggles whether the user can sort data by the column
  • sorter – How to sort data in the column (defaults to string)
  • formatter – How to format data in the column (defaults to string)
  • onClick – Callback for when user clicks on a cell in the column
  • editable – Determines if this data is editable by the user
  • editor – Editor to be used when cell in the column is editable
  • visible – Show or hide the column

Loading Data into Your Table

The final stage of building your new Tabulator is to load in some data. There are several options for this, and we will touch briefly on each one here.

JavaScript array

You can pass in an array of data using the setData method. This takes an array, with each row of the table being defined by an object.

Lets create some sample data:

var sampleData = [
  {id:1, name:"Oli Bob", progress:12, gender:"male", rating:1, col:"red", dob:"", car:1, lucky_no:5, cheese:"Cheader"},
  {id:2, name:"Mary May", progress:1, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10, cheese:"Gouda"},
  {id:3, name:"Christine Lobowski", progress:42, gender:"female", rating:0, col:"green", dob:"22/05/1982", car:"true", lucky_no:12, cheese:"Manchego"},
  {id:4, name:"Brendon Philips", progress:100, gender:"male", rating:1, col:"orange", dob:"01/08/1980", lucky_no:18, cheese:"Brie"},
  {id:5, name:"Margret Marmajuke", progress:16, gender:"female", rating:5, col:"yellow", dob:"31/01/1999", lucky_no:33, cheese:"Cheader"},
];

Then assign it to our table:

$("#example-table").tabulator("setData", sampleData);

Ajax request

To retrieve JSON formatted data from a remote source, you can pass a URL to the setData method and it will perform the Ajax request for you.

$("#example-table").tabulator("setData", "http://www.exampleurl.com/data");

Additional request parameters can be passed in an object with the URL.

$("#example-table").tabulator("setData", "http://www.exampleurl.com/data", {key1:"value1", key2:"value2"});

HTML table

You can also convert an existing HTML table into a Tabulator.

Create your HTML table:

<table id="example-table">
  <thead>
    <tr>
      <th width="200">Name</th>
      <th>Progress</th>
      <th>Gender</th>
      <th>Height</th>
      <th>Favourite Color</th>
      <th>Date of Birth</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Billy Bob</td>
      <td>12</td>
      <td>male</td>
      <td>1</td>
      <td>red</td>
      <td></td>
    </tr>
    <tr>
      <td>Mary May</td>
      <td>1</td>
      <td>female</td>
      <td>2</td>
      <td>blue</td>
      <td>14/05/1982</td>
    </tr>
  </tbody>
</table>

Then call the Tabulator constructor on the table element to extract the headers and data automatically:

$("#example-table").tabulator({});
--ADVERTISEMENT--

The End Result

You have built your table, defined your columns and loaded your data, now you have a fully functioning interactive table. Your working Tabulator should look something like this:

See the Pen Tabulator Tutorial – Simple Table by SitePoint (@SitePoint) on CodePen.

Additional Features

But wait there’s more! Why settle for a simple text based table when there is so much more that can be done to improve the look, feel and interactivity of your table. In the next few sections, we will cover some of the additional features you can add to enhance your Tabulator.

Sorting

Sorting is enabled by default on all columns, clicking on any column header will sort the data by that column.

Sorting can be enabled or disabled on a per-column basis using the sortable parameter.

$("#example-table").tabulator({
  columns:[
    {title:"Name", field:"name",  sortable:true}, //sorting enabled
    {title:"Progress", field:"progress", sortable:false}, //sorting disabled
  ],
});

By default, all columns are sorted as text. You can specify a different sorter with the sorter parameter.

$("#example-table").tabulator({
  columns:[
    {title:"Name", field:"name",  sortable:true}, //sort as string (default)
    {title:"Progress", field:"progress", sortable:true, sorter:"number"}, //sort as number
  ],
});

Several builtin sorters are available:

  • string – Sorts as strings of characters (default option)
  • number – Sorts as numbers (integer or float, will also handle numbers using “,” separators)
  • alphanum – Sorts as alpha numeric string
  • boolean – Sorts as booleans
  • date – Sorts as dates

To define a custom sorter, pass a callback to the sorter parameter. It should return the difference between the two values being compared.

var customSorter = function(a, b, aData, bData){
  //a and b are the two values being compared
  //aData and bData are the row objects for the values being compared (useful if you need to access additional fields in the row data for the sort)

  return a - b; //return the difference between the two values
}

$("#example-table").tabulator({
  columns:[
    {title:"Progress", field:"progress", sortable:true, sorter:customSorter},
  ],
});

Formatting

With Tabulator, you’re not fixed to displaying your data as plain text. Using formatters you can decide how you want each column to look.

A variety of inbuilt formatters are included:

  • plaintext – Display the value of the cell as text. (default option)
  • textarea – Shows text with carriage returns intact (great for multiline text)
  • money – Formats a number into currency notation (eg. 1234567.8901 -> 1,234,567.89)
  • email – Renders data as an anchor with a mailto: link to the given value
  • link – Renders data as an anchor with a link to the given value
  • tick – A green tick if the value is (true|’true’|’True’|1) and an empty cell if not
  • tickCross – A green tick if the value is (true|’true’|’True’|1) and a red cross if not
  • star – A graphical star rating based on integer values
  • progress – A progress bar that fills the cell from left to right (using values 0-100 as a percentage of width)

You can set a column’s formatter with the formatter parameter.

$("#example-table").tabulator({
  columns:[
    {title:"Progress", field:"progress", formatter:"progress" },
  ],
});

To define a custom formatter, pass a callback to the formatter parameter. The callback should return the HTML to be displayed in the cell.

var customFormatter = function(value, data, cell, row, options, formatterParams){
  //value - value of the cell
  //data - data for the row the cell is in
  //cell - DOM element of the cell
  //row - DOM element of the row
  //options - options set for this tabulator
  //formatterParams - parameters set for the column

  return "<div></div>"; // must return the HTML or jQuery element for the contents of the cell;
}

$("#example-table").tabulator({
  columns:[
    {title:"Progress", field:"progress", formatter:customFormatter},
  ],
});

Filtering

There are often times when you need to only display a subset of data to your users. You can filter data using the setFilter function.

$("#example-table").tabulator("setFilter", "progress", ">", 10);

The function takes three arguments, the field to be filtered, the comparison function (=, <, <=, >, >=, !=, like), and the filter value.

To perform a more complex filter you can pass a callback to the setFilter function. The callback must return a boolean, with true representing a match.

var customFilter = (data){
  //data - data for the row being filtered

  return data.name == "bob" && data.progress < 50; //must return a boolean, true if it passes the filter.
}

$("#example-table").tabulator("setFilter", customFilter);

Clear existing filters with the clearFilter function.

$("#example-table").tabulator("clearFilter");

Editing

One of the major benefits of using Tabulator over a standard HTML table is the ability to edit data in the table.

A number of preconfigured editors are available:

  • input – Plain text
  • textarea – Multi-line text, allows the row to vertically resize to fit the text as it is entered
  • number – Numbers with increment and decrement buttons
  • tick – Checkbox
  • star – Star ratings (can use left/right arrow keys and enter for selection as well as mouse)
  • progress – Progress bar (can use left/right arrow keys and enter for selection as well as mouse)

Columns can be set as editable using the editable parameter.

$("#example-table").tabulator({
  columns:[
    {title:"Progress", field:"progress", formatter:"progress", editable:true},
  ],
});

By default, an editor will be used that matches the formatter for that column. To specify a different editor, use the editor parameter.

$("#example-table").tabulator({
   columns:[
    {title:"Progress", field:"progress", formatter:"progress", editable:true, editor:"number"},
  ],
});

To define a custom editor, pass a callback to the editor parameter. It should return the editor element to be displayed in the cell. Returning false will abort the edit and prevent the cell from being selected.

var customEditor = function(cell, value, data){
  //cell - JQuery object for current cell
  //value - current value for current cell
  //data - data for the current row

  //create and style editor
  var editor = $("<select><option value=''></option><option value='male'>male</option><option value='female'>female</option></select>");

  editor.css({
    "padding":"3px",
    "width":"100%",
    "box-sizing":"border-box",
  });

  //set value of editor to the current value of the cell
  editor.val(value);

  //when the value has been set, trigger the cell to update
  editor.on("change blur", function(e){
    cell.trigger("editval", editor.val());
  });

  //return the editor element
  return editor;
}

$("#example-table").tabulator({
  columns:[
    {title:"Gender", field:"gender", editable:true, editor:customEditor},
  ],
});

To access the data stored in the table, use the getData function. This will return an array of row data objects.

var data = $("#example-table").tabulator("getData");

A Fully Featured Example

If we combine all the lessons we have learned above, we can create a feature-rich, interactive table.

See the Pen Tabulator Tutorial – Fully Featured Table by SitePoint (@SitePoint) on CodePen.

The Tip of the Iceberg

We have covered how to create a basic Tabulator and add features to enhance its appearance and usability.

This article only covers the tip of the iceberg when it comes to creating and customizing your tables. The library is packed with features to help provide an even richer experience for users:

  • Row grouping
  • Movable rows and Columns
  • Pagination
  • CSS Styling and Theming
  • Progressive rendering for large data sets
  • Persistent column layout (stores user preferences in a cookie)
  • Callbacks at every stage of table rendering and every type of user interaction

I hope this article has shown you how to take your basic HTML tables to the next level, adding interactivity and style to your data.

Happy Tabulating!

  • Michael Iversen

    Interesting. Very interesting, in fact.
    Thanks!

  • TimA11y

    Does this widget generate an HTMl table from the JSON or just create something that looks like a table? I was trying to check the results with a screen reader and it doesn’t appear that the widget generates an actual table from the data–which presents some accessibility issues.

    • Oliver Folkerd

      It creates the visual look of a table using a range of elements as It is impossible to add the level of functionality present in Tabulator to a standard HTML table. This months release will include a range of accessibility updates that should make it easier to traverse.

  • Oliver Folkerd

    Tabulator offers a more diverse range of features than datatables. it is also easier to configure the more complex elements like sorters, filters and editors. The option to choose to save state as either a cookie or in localStorage will be coming in this months release

  • TimA11y

    Is the plan to use aria grid to make the table accessible? Do you have any ideas how long before that support is added? I like the widget, but I can’t use it in any of my work unless it is accessible

    • Oliver Folkerd

      Thats correct. we will be using aria. the good news is, It should be going in this weekend!

  • Oliver Folkerd

    Version 2.8 of Tabulator has just been released, complete with localStorage persistent column layout storage options.

    If you would like to see a full list of the features available on Tabulator, have a look at our documentation page: http://olifolkerd.github.io/tabulator/docs/

  • Lloyd McDermott

    Is there a limit to the number of records that can be retrieved? I have been experimenting with my database with over 3000 records. I can only get it to work when selecting a maximum of TOP 30 using sql server.

  • Oliver Folkerd

    Hi Lloyd,

    If you are getting a loading error it suggests there is an error on the server not in the Tabulator.

    Luckily there is a dataLoadError callback you can use to find out more about the error.

    I have created an issue for you on the Tabulator GitHub page so we can work through it together. please follow this link and make any new comments about the bug on the issue in GitHub. https://github.com/olifolkerd/tabulator/issues/95

    • Lloyd McDermott

      Thanks for the suggestion. You are brilliant. I redid the data.php file, not using Zend. After quite a few missteps, I eventually got it to work. It works very well indeed and quite fast. I have previously tried other techniques and by comparison, this is much faster.

Recommended
Sponsors
Get the latest in JavaScript, once a week, for free.