Tutorial: Angular 2 Datatable with Sorting, Filtering and Resizable Columns

In this tutorial I’m going to show you one of the datatable solutions available for Angular 2, it’s called ag-Grid and it’s available not only for angular2, but also for other frameworks like Angular 1 and React. It’s a really complete datatable, it has lots of features that I definitely want to explore in other tutorials, but in this one I’ll try to keep it as simple as possible, my goal is to just make it display the data and enable the sorting, filtering and the resizable columns features. Maybe in the future I’ll write a PART 2 of this tutorial explaining how to add some more complex functionality. If you don’t want to use ag-grid take a look at this post.

I’m assuming you already have your Angular 2 project ready, but if you don’t just follow the instructions on this link to set up your environment, it’s really easy and straightforward, all you need to do is to create three configurations files: tsconfig.json, typings.json and package.json, make sure you have all of them before you continue.

Now let’s add the ag-grid to the project, to do that you have to add these two lines to the dependencies list on your package.json:

{
  "dependencies": {
    "ag-grid": "3.3.x",
    "ag-grid-ng2": "3.3.x"
    ...
  },
}

Run npm install to download and install the dependencies, when it completes we’ll be ready to start writing some code!

Open your project folder and create another one inside called app, that’s where we’re going to put all our Angular2 related code. The first file we are going to create on this folder is the app.component.ts, it should contain the following code, just copy and paste it into the file:

import {Component} from 'angular2/core';
import {AgGridNg2} from 'ag-grid-ng2/main';
 
@Component({
    selector: 'my-datatable',
    directives: [AgGridNg2],
    template: `
         <ag-grid-ng2 #agGrid style="height:100%;width:845px" class="ag-fresh"
            [gridOptions]="gridOptions">
         </ag-grid-ng2 >
     `
})
 
export class AppComponent { 
    myRowData = [
        {"name":"Ronald Bowman","country":"China","city":"Lutou","email":"rbowman0@spotify.com"},
        {"name":"Pamela Hill","country":"Russia","city":"Krylovskaya","email":"phill1@symantec.com"},
        {"name":"Robin Andrews","country":"Ukraine","city":"Korop","email":"randrews2@photobucket.com"},
        {"name":"Peter Kim","country":"Mexico","city":"San Jose","email":"pkim3@theatlantic.com"},
        {"name":"Carol Foster","country":"Mexico","city":"El Aguacate","email":"cfoster8@intel.com"},
        {"name":"Jimmy Burke","country":"Indonesia","city":"Banjarsari","email":"jburke9@over-blog.com"},
        {"name":"Jonathan Crawford","country":"Peru","city":"Alca","email":"jcrawforda@deliciousdays.com"},
        {"name":"Donald Montgomery","country":"Poland","city":"Działoszyce","email":"dmontgomeryb@google.com.br"},
        {"name":"Donna Shaw","country":"Japan","city":"Akune","email":"dshawc@chronoengine.com"},
        {"name":"Helen King","country":"United States","city":"Hollywood","email":"hkingd@devhub.com"},
        {"name":"Walter Myers","country":"China","city":"a ndaowa n", "email":"wmyerse@state.tx.us"},
        {"name":" Alice Collins","country":"Papua Nw  Guine a", "city":"Mendi","email":"acollinsf@npr.org"},
        {"name":"Anne Richards","country":"China","city":"Koramlik","email":"arichardsu@vinaora.com"},
        {"name":"Randy Miller","country":"Indonesia","city":"Trenggulunan","email":"rmillerv@oakley.com"},
        {"name":"Phillip Adams","country":"Bahamas","city":"Duncan Town","email":"padamsw@lycos.com"},
        {"name":"Nicholas Allen","country":"Philippines","city":"Bautista","email":"nallenx@aboutads.info"},
        {"name":"Lisa Willis","country":"Thailand","city":"Lat Yao","email":"lwillisy@istockphoto.com"},
        {"name":"Jeffrey Castillo","country":"Indonesia","city":"Karangsari","email":"jcastilloz@washington.edu"},
        {"name":"Michael Carpenter","country":"Colombia","city":"Cali","email":"mcarpenter13@prlog.org"},
        {"name":"Roger Lee","country":"France","city":"Courtaboeuf","email":"rlee14@earthlink.net"},
        {"name":"Steve Wallace","country":"Russia","city":"Novobeysugskaya","email":"swallace15@cisco.com"},
        {"name":"Shirley Patterson","country":"Peru","city":"La Tinguiña","email":"spatterson16@woothemes.com"},
        {"name":"Nancy Ward","country":"Sweden","city":"Båstad","email":"nward17@mapquest.com"}
    ];
 
    columnDefs = [
        {headerName: 'Name', field: "name", width: 200 },
        {headerName: 'Country', field: "country" ,width:180},
        {headerName: 'City', field: "city" ,width:160},
        {headerName: 'e-mail', field: "email" ,width:300}
    ];
 
    gridOptions = [];
 
    constructor() {
        this.gridOptions = {
            rowData: this.myRowData,
            columnDefs: this.columnDefs,
            enableColResize: true,
            enableSorting: true,
            enableFilter: true
        }   
    }
}

There is quite a lot to explain about this code, I’m going to start with the class AppComponent, that’s where we’re going to put all the parameters and configurations that makes our datatable work, we have three variables on this class: myRowData, columnDefs and gridOptions.

myRowData: This variable will store the data to be displayed on the table, for this example I’m just going to use some JSON data I generated, but in a real case scenario you would get the data from your database or a web service.

columnDefs: This one will store an object containing information about every column of our datatable, I’m just using the attributes headerName to define the column title, field to tell which array attribute will be displayed on the column and width to define the size of each column. Although I’m using only three, there are tons of other attributes you could specify here.

gridOptions: This one just wraps everything up and make it available to the component. It’s being initialized empty, but in the constructor I’m setting its value, besides the rowData and columnDefs I’m also specifying the attributes enableColResize, enaleSorting and enableFilter. They will do exactly what their names suggests, enable the columns resize, sorting and filtering features respectively.

Now we can create our component, to be able to use the directive AgGridNg2 we have import it first with the line import {AgGridNg2} from 'ag-grid-ng2/main, after that all you need to do is to pass the gridOptions to the ag-grid-ng2 component on the template.

Before we write the index.html we’re going to need one more ts file to be able to launch our application, on your app folder create the file main.ts and paste the following code into it:

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'
 
bootstrap(AppComponent);

Now you can create the index.html file on your project root folder, let’s take a look at the code:

<html>
  <head>
    <title>Datatable</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">    
    <script src="node_modules/es6-shim/es6-shim.min.js"></script>
    <script src="node_modules/systemjs/dist/system-polyfills.js"></script>
    <script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <script src="node_modules/rxjs/bundles/Rx.js"></script>
    <script src="node_modules/angular2/bundles/angular2.dev.js"></script>
    <link href="node_modules/ag-grid/dist/styles/ag-grid.css" rel="stylesheet" />
    <link href="node_modules/ag-grid/dist/styles/theme-fresh.css" rel="stylesheet" />
    <script>
      System.config({
        packages: {        
          app: {
            format: 'register',
            defaultExtension: 'js'
          },        
          lib: {
            format: 'register',
            defaultExtension: 'js'
          },
          'ag-grid-ng2': {
            defaultExtension: "js"
          },
          'ag-grid': {
            defaultExtension: "js"
          }
        },
        map: {
            'ag-grid-ng2': 'node_modules/ag-grid-ng2',
            'ag-grid': 'node_modules/ag-grid'
        }
      });
      System.import('app/main')
            .then(null, console.error.bind(console));
    </script>
  </head>
  <body>
    <my-datatable>Loading...</my-datatable>
  </body>
</html>

This file will basically be used just to load the necessary scripts and to configure SystemJS to load everything and launch the application. Finally you can use your component here calling it by the selector we specified before: my-datatable.

We’re done!! To run the project open your terminal, navigate to your project folder and run npm start, this should be the result: my-datatable.

Angular 2 Datatable with Sorting, Filtering and Resizable Columns
Angular 2 Datatable with Sorting, Filtering and Resizable Columns

20 comments on “Tutorial: Angular 2 Datatable with Sorting, Filtering and Resizable Columns

  1. Andrew Torr

    In the constructor I’m getting the error:

    "Type '{ rowData: { "name": string; "country": string; "city": string; "email": string; }[];
     columnDefs:...' is not assignable to type 'any[]'.at line 51 col 9"

    Any idea what’s missing?

  2. Ofer Gal

    Having problem running “npm start”

    app/app.component.ts(48,5): error TS7008: Member 'gridOptions' implicitly has an 'any[]' type.
    app/app.component.ts(51,9): error TS2322: Type '{ [x: number]: undefined; rowData: { "name": 
    string; "country": string; "city": string; "email": ...' is not assignable to type 'any[]'.
      Property 'length' is missing in type '{ [x: number]: undefined; rowData: { "name": string; 
    "country": string; "city": string; "email": ...'.
     
    npm ERR! Windows_NT 10.0.10586
    npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs
    \\node_modules\\npm\\bin\\npm-cli.js" "start"
    npm ERR! node v4.4.3
    npm ERR! npm  v2.15.1
    npm ERR! code ELIFECYCLE
    npm ERR! angular2-DataGrid@1.0.0 start: `tsc &amp;&amp; concurrently 
    "tsc -w" "lite-server" `
    npm ERR! Exit status 2
    npm ERR!
    npm ERR! Failed at the angular2-DataGrid@1.0.0 start script 'tsc &amp;&amp; concurrently 
    "tsc -w" "lite-server" '.
    npm ERR! This is most likely a problem with the angular2-DataGrid package,
    npm ERR! not with npm itself.
    npm ERR! Tell the author that this fails on your system:
    npm ERR!     tsc &amp;&amp; concurrently "tsc -w" "lite-server"
    npm ERR! You can get information on how to open an issue for this project with:
    npm ERR!     npm bugs angular2-DataGrid
    npm ERR! Or if that isn't available, you can get their info via:
    npm ERR!
    npm ERR!     npm owner ls angular2-DataGrid
    1. John Baird

      if you change gridOptions: []; to gridOptions: any; it doesn’t throw any errors. I can’t get it to work because I’m on RC3. Hope this helps…

  3. Joe

    This works! Sadly, the code straight from the ag-grid doesn’t work… so I went searching. Finding this makes me extremely happy. Thanks!

  4. John Baird

    I have looked all over for a data grid and this looks really promising. I’m on RC3 and since there is no source code available, can you at least upgrade it and make that available?

  5. Alan

    We really need the source code for this because running this after npm install and npm start does not work. the @angular folder is not able to find bootstrap also. Please help.

  6. Barry Docherty

    The trouble with these tutorials they are not thorough. The app.component.ts can’t find ‘angular2/core';
    main.ts can’t find ‘angular2/platform/browser’

    Total failure. Probably because ng2 is changing rapidly rendering this tutorial obsolete.

    1. Barry Docherty

      oh and you forgot to add a comma:

      {
        "dependencies": {
          "ag-grid": "3.3.x",
          "ag-grid-ng2": "3.3.x", &lt;--HERE
          ...
        },
      }
  7. Mike J

    Great example!

    I’m in RC5. How to import ag-grid.css and theme-fresh.css into project?

    I don’t want to link them in index. html’s header.

  8. Jon

    Data binding to remote data source.

    Remote data binding:

    How would I connect a managed bean to your component?

    My main interest is:

    HIERARCHY – nested grid / row detail (child)
    Global SEARCH as you type
    Column FILTER as you type
    Column SORTING as you type
    PAGING

    Highlight search as you type

    <pre lang=

    queryData

    Number
    #{u.caseno}

Leave a Reply to John Baird Cancel reply

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

Obs: Use the tag <pre lang="LANGUAGE"> to include code blocks to your comment.
Example: <pre lang="javascript"> console.log('Test'); </pre>