tables in dining room

Sorting table dates in a Vue CLI project

Update August 5, 2020 (originally posted on October 9, 2019)

Lately, I found another table plugin, called Grid.js – Advanced table plugin, and given it included a Vue plugin I was interested. After implementing, I came to the conclusion this was clearly the best plugin in terms of performance but took a little more diy to make it work.

The Grid.js option is added in the text below and I added an extra part about performance.


It happens in many projects. You start with a rather simple table to give your client an overview of some entity, say users. When the project evolves, the number of columns changes and at some point, the client requires the table to be sortable, searchable and so on. My first pick for such a table is the neat Datatables plugin

Datatables requires jQuery and has a very large set of options and capabilities so it may take a while to know how it works exactly. Fortunately, there is a lot of documentation and a helpful support forum.

In a recent project I had to use Datatables to sort a column with dates in the format dd-mm-yyyy (the default date format in the Netherlands). Additionally, the assets are compiled with Webpack and ES6 imports are used in this project. I made it work, but it took me quite some time to find out how to do it. 

I wondered whether it is possible to use this plugin in a Vue table component. It turns out this is not so complicated once you know how to do it. I’ll summarize what I have done for you and my future self 😉

In addition, I found the Tabulator project and Grid.js (both including a Vue plugin) in a newsletter. I gave it a try and it works very Vue-ish. Tabulator comes with a lot of features but is relatively heavy weight. Grid.js on the other hand is light weight but leaves the details of sorting dates to the user.

Given that performance is increasingly important in our applications, I definitely use Grid.js in my next Vue project calling for an interactive table!

Using three plugins to sort table data.

Code samples

You can find all code in this sample project on Github. Just clone or download it, install dependencies and give it a go!

Sample project setup

I have set up a new project using the Vue CLI graphical user interface by typing ‘vue ui’ in the terminal. I configured the project manually and only took the babel plugin to start. After running the task serve, which installs the required node_modules, I installed the following dependencies one by one via the UI:

  • jquery
  • datatables.net
  • datatables.net-plugins
  • moment
  • less
  • less-loader

In addition, I like to use the Font Awesome (v4) icons so I downloaded the css file from the website, added it to my src folder manually and imported it in the main.js file.

The last step was to remove the Hello World sample component.

Sortable Datatable component

I create a new component in the components folder, called SortableDatatable.vue. The template is rather simple, it contains a container div with a table holding some hardcoded data. For the purpose of this demo, the table contains user data with names, locations, dates of birth and last login dates.

The script part of the component is the most interesting. Since datatables depends on jQuery to be available as $, importing jQuery goes like this

import $ from ‘jquery’

Then I import datatables itself, followed by moment and the datatables plugin for sorting. Note that the datatables.net-plugins module contains all kinds of handy plugins to extend the behavior of datatables (filtering, internationalization, pagination to name a few).

According to the docs of the ‘date sorting with moment’ plugin, for each date column a format is required to tell Datatables how to sort it. If these lines are omitted, normal alphabetical sorting is applied which yields wrong results if the dates are in the format used here. In this example there are two date columns with dates in the format dd-mm-yyyy and in normal English (e.g., Tuesday, September 10 2019) respectively. Hence, we need to add two formats. The moment docs give us all we need, and formats are defined as follows:

$.fn.dataTable.moment('DD-MM-YYYY');
$.fn.dataTable.moment('dddd, MMMM D YYYY');

Finally, the Datatables plugin is instantiated in the mounted hook of the component.

Basically this is all we need for correct date sorting, when modules are imported using the ES6 syntax.

The SortableDatatable component can be found in the project on Github.

And now we do it the Vue way with Tabulator

I found out about this project Tabulator last week and this demo is a perfect place to try the Vue plugin that comes with it. This way we can remove our dependency on jQuery. Moreover, with vue-tabulator, as the package is called, things go the Vue way.

First install the package with

npm install --save vue-tabulator

and import it in your main.js file and make it ‘usable’:

import VueTabulator from vue-tabulator
Vue.use(VueTabulator)

I create the table component SortableTabulator and import it in App.vue (not shown).

To be able to use the default styling of VueTabulator the default stylesheet is imported in App.vue. However, since the stylesheet is a .scss file, node-sass and sass-loader are required as dependencies of our project.

Once the setup is done, the template part of the SortableTabulator is extremely simple. Again, I create some dummy data and set up the VueTabulator component with some options.

The data should be an array of objects. Each object resembles one row in the table and each property of this object corresponds to a column.

This package also comes with a lot of options, but I’ll keep it as simple as possible in this example. You have to define a height for the table. If you choose it too small, some rows will not be displayed. For my small table I chose a height of 500px. Furthermore, a layout property was added with value ‘fitColumns’ to fit all columns nicely over the available width.

The most important property is ‘columns’. If you leave it out, the package will try to figure it all out by itself, but with the current sorting requirements, it is better to be explicit about the columns. The columns property is also an array of objects and describes the columns of the table. The title property is used for the header row of the table, the field property should match the name of the column used as properties in the data array.

The default sorting algorithm assumes that the content of the column is a string (as in the datatables plugin), but in this situation the properties ‘sorter’ and ‘sorterParams’ are required. Since the moment.js library is already available I just set the correct format for sorting and we are good to go. 

You can find the full component on Github.

Finally, meet Grid.js

The last plugin we add is Grid.js. The vue plugin is installed by running

npm install --save gridjs-vue

Additionally, to sort dates we’ll use dayjs. Even though this project uses moment (as the other plugins depend on it), we’ll shortly see in the section on performance, that dayjs is the light weight alternative. Install it like so

npm install --save dayjs

As before, I create a new component SortableGrid and import in App.vue (not shown).

The component looks like this (explanation follows below)

The template is rather simple: we just include a grid instance that is imported from gridjs-vue. The script part is more interesting.

First, we import gridjs and dayjs. Additionally, we extend dayjs with the customParseFormat option, to show the dates in the last column in the special format.

The Grid component needs columns and rows (containing our data) and we need to set sort to enable it. Columns is an array of objects describing each column. We specify a name and a width and for the last two columns we also specify a special sort function. The last column needs the special formatter in order for the sort function to work properly.

Sorting is done using a custom compare function. If this function is omitted, a standard sorting is applied which works well for names and cities/countries, but not for dates. We have to instruct the sorting algorithm how we like the sorting to take place. This is where we have to do more work ourselves compared to the Vue Tabulator example above.

The compare function receives two column entries as inputs (in the variables a and b). Depending on which column (‘Date of birth’ or ‘Last login date’), the format of the date is different. To be able to sort them, I convert the dates to unix timestamps which can easily be compared: I use dayjs’ constructor with the format the date is currently in and call the unix method to convert to a unix timestamp.

For the Last login date column, we also need a formatter, otherwise dayjs won’t understand the format.

A word on performance

When working on this demo, I got a bit worried about the performance. With the Vue CLI it is actually quite easy to analyse the size of your bundle. For this, I created three separate projects in which I only included the necessary dependencies for the demos to run. Below is the result of the analysis in which I look specifically at parsed code size for the chunk-vendors, as the app code is very small in this demo.

DatatablesTabulatorGrid.js
gridjs-vuexx4
dayjsxx9
core-js232328
gridjsxx58
vue-tabulatorx52x
moment (ex locales)5959x
vue646464
datatables.net82xx
jquery88xx
tabulator-tablesx334x
TOTAL316532163
TOTAL (ex Vue)25246899
Comparing parsed vendor bundles (in kB)

I think it is rather clear from this table that Grid.js is light weight (163 kB) compared to the other options (316 kB and 532 kB respectively for Datatables and Vue Tabulator). Tabulator-tables is really heavy with 334 kB and also the combination of jquery + datatables + moment is rather heavy. Moment’s weight of 59 kB is only possible if we ignore all locales as described below. If you need some locales other than English this adds up quickly.

With this in mind, I’ll definitely use Grid.js in my next project!

Chunk-vendors for Grid.js only app. Analyse your bundle to improve performance!

A quick note on the performance of moment.js which we depend heavily on in two out of three implementations. It is a rather large module due to all the i18n files that are loaded out of the box. Most projects will only use a few languages at most and the bundle size of your compiled app can be reduced significantly by not bundling all those language files. Have a look at my vue.config.js file to see how simple it is to ignore all locale files.

const webpack = require('webpack')
module.exports = {
    configureWebpack: {
        plugins: [
            // Ignore all locale files of moment.js
            new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
        ],
    },
};

If you still need to import one, have a look at main.js where the commented lines 9-12 show how to import a locale:

// Although we ignore moment's locales, we may import a single language like so
require('moment/locale/nl')
moment.locale('nl')
console.log('current date: ', moment().format('dddd, MMMM D YYYY'))

I found this handy trick by first reading this and consequently by following moment’s docs and arriving here.

Concluding remarks

In this post I have shown three ways of adding date sorting to a table in a Vue CLI project. The first approach using jQuery and Datatables.net works fine but feels a bit old fashioned. It does the job and it works nicely, but it simply does not feel like working in Vue.

The second approach felt a lot more natural by using Vue’s data binding and a plugin created to work with Vue.

The third approach, using Grid.js was even better as we did not depend on moment anymore. The downside (if you can call it that) is more work to define the sorting/compare function.

For the sake of this post I kept the table data to a minimum. There are all kinds of extensions and improvements possible:

  • $.fn.dataTable.moment(format) takes a second argument, a locale (e.g., ‘nl’) to make this work for dates in your preferred language.
  • Table data is hardcoded in these examples but it is simple enough to add some logic to read the data from a server.

The main image is a photo by Ibrahim Boran on Unsplash.


Mijn Twitter profiel Mijn Facebook profiel
Pim Hooghiemstra Webdeveloper and founder of PLint-sites. Loves to build complex webapplications using Vue and Laravel! All posts
View all posts by Pim Hooghiemstra

Leave a Reply

Your email address will not be published. Required fields are marked *