Kenneth Ekandem Software engineer with four years' experience in PHP and JavaScript. Currently working as a backend developer for Codekago Interactive.

Using Angular DataTables to build feature-rich tables

6 min read 1853

Using Angular DataTables for Feature-rich Tables

Data tables were introduced to simplify the process of visualizing, grouping, querying, and sorting data. Normally, a table is just a tabular form of data and has nothing special about it. But a data table may offer multiple features, including data sorting, data querying, updating of data, pagination, printing, and data exports, and more.

Making use of a data table in a framework like Angular, which makes constant updates to its codebase, presents a few complications:

  • Deprecated code: Angular DataTables, which we will be using for this article, doesn’t support older versions of the Angular CLI (Angular 8 and below). Even older versions of Node and npm use deprecated code and therefore cannot use the service
  • Configuration: Every developer will agree that some configurations can be a real pain, and data table configuration in Angular is no exception

What is Angular DataTables?

Angular DataTables is a library for building complex HTML tables that uses jQuery’s DataTables plugin. It is configured to support TypeScript and optimized for Angular 2+.

Angular DataTables will come in handy when:

  • You have a very large dataset coming in from one or more API endpoints
  • You need customized data sorting/filtering
  • You need to export and print data from a table

Angular DataTables features can be broadly grouped into two sets: basic and advanced. From there, Angular DataTables also supports a number of extensions.

Basic features

  • Direct loading of data using AJAX calls
  • Options such as column rendering in your Angular components
  • Table rendering using the custom function dtTrigger
  • Server-side processing (though you’ll need to override the AJAX option)

Advanced features

  • Custom filtering, which covers filtering by numbers, strings, Booleans, etc.
  • Individual column filtering, which sorts data by column
  • Re-rendering of data table
  • Multiple tables can be displayed simultaneously
  • Router links can be added in the Angular components, which can display a single instance of data in a new page
  • Pipes are added in the data table to transform data to the format you want

Installing Angular DataTables

Let’s now dive into installing and using Angular DataTables. To start, we will install our Angular application, then install DataTables into the application:

ng new angular-datatable

When the Angular installation is done, you can then step into the directory in your terminal and install DataTables:

cd angular-datable

ng add angular-datatables

This will add jQuery and the DataTables plugin to your angular.json file and your application. When the installation is done, you can then import your data table module in app.module.ts to use it globally across the application:

// src/app/app.module.ts

import {DataTablesModule} from 'angular-datatables';

imports: [
  BrowserModule,
  AppRoutingModule,
  DataTablesModule,
],

Making an API call

We’ll use the JSONPlaceholder API to populate our data table with information to take Angular DataTables for a spin.

To do that, we will first have to add the HttpClient module in our app.module.ts file to make it accessible in our services for HTTP requests. We do so by importing it and calling it in the imports array:

We made a custom demo for .
No really. Click here to check it out.

// src/app/app.module.ts

import { HttpClientModule } from '@angular/common/http';

imports: [
  BrowserModule,
  AppRoutingModule,
  DataTablesModule,
  HttpClientModule
],

Creating an Angular service

We’ll create an Angular service that will communicate with our HTTP module to fetch data from our API. To generate the service, we’ll run the below command in the terminal:

ng generate service services/users/users

This will create a new file directory in our src/app folder containing our users.services.ts file:

-| Users/
    users.service.spec.ts
    users.services.ts

We can then import our HttpClient in our users.service.ts file:

// src/app/services/users/users.service.ts

import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) { }

Next, we add our function, which will get users from the API link:

users() {
  this.http.get('https://jsonplaceholder.typicode.com/users');
}

Generating a component

After creating the service, we then generate a component with the name users, which will hold the data we get from the service we just created and display it in our HTML page. We’ll also use the users component to create our data table and all the functionalities.

To create a component, simply run the following command:

ng generate component components/users

Consuming the API

In our users components, we will consume the API data fetched from the service we created and store it in an array named allUsers:

import { UsersService } from '../../services/users/users.service';

export class UsersComponent implements OnInit {

  allUsers: any = [];
  constructor(private service: UsersService) { }

  ngOnInit(): void {
    this.users();
  }

  users(): void {
    this.service
        .users()
        .subscribe((response: any) => {
          this.allUsers = response.data;
        });
  }

}

Then we populate our users.component.html with our fetched users:

<div class="container">
    <div class="card m-5 p-3">
        <div class="card-body">
            <table class="table table-bordered table-striped table-hover">
                <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Username</th>
                    <th>Email</th>
                    <th>Phone number</th>
                    <th>Address</th>
                </tr>
                </thead>
                <tbody>
                <tr *ngFor="let user of allUsers">
                    <td>{{ user.id }}</td>
                    <td>{{ user.name }}</td>
                    <td>{{ user.username }}</td>
                    <td>{{ user.email }}</td>
                    <td>{{ user.phone }}</td>
                    <td>{{ user.address.street }}, {{ user.address.city }}</td>
                </tr>
                </tbody>
            </table>
        </div>

    </div>
</div>

It will display something like this:

Users Data Table Without Styling

Now that this is done, crack your fingers because we’re about to dive into data table usage and manipulation! 😋

Adding our data table

Since we already added our data table module in app.module.ts, we won’t have to import it in our component; we simply call it as a subject using rxjs:

// src/app/components/users/users.components.ts
import {Subject} from 'rxjs';
...

export class UsersComponent implements OnInit {

  dtOptions: DataTables.Settings = {};
  dtTrigger: Subject<any> = new Subject<any>();

}

Then we add our unsubscribe function to the Angular OnDestroy module:

import { Component, OnInit, OnDestroy } from '@angular/core';

export class UsersComponent implements OnInit, OnDestroy {
  ...
}

ngOnDestroy(): void {
  this.dtTrigger.unsubscribe();
}

This will reset the data table every time we leave the page attached to the component.

With that, we will now add a data table to our users function and a users table in our component HTML:

users(): void {
  this.service
      .users()
      .subscribe((response: any) => {
        this.allUsers = response;
        // initiate our data table
        this.dtTrigger.next();
      });
}
<table class="table table-bordered table-striped table-hover" datatable [dtOptions]="dtOptions" [dtTrigger]="dtTrigger">
  ...
</table>

Filtering and pagination have been added to the table, as you can notice in the image below:

Users Data Table with Filtering and Pagination Options

Custom filtering

There may be times when we wish to search data presented to the end user in our own manner. Common examples include number range searches (in between two numbers) and date range searches. Angular DataTables allows you to make those custom searches easily and effortlessly.

N.B., the documentation for custom filtering in Angular DataTables is faulty, mainly because of updates in TypeScript with Angular, so follow my examples instead.

To initiate custom filtering, we will first import a @ViewChild decorator, which allows us to inject into a component class references to elements used inside its template:

import {Component, OnInit, OnDestroy, ViewChild} from '@angular/core';

Then, we import DataTableDirective in our component:

import {DataTableDirective} from 'angular-datatables';

We then reference our DataTableDirective and assign it to a new variable datatableElement. After that, we will create max and min variables, which will take the maximum and minimum numbers for our custom filtering.

Let’s begin with the referencing:

@ViewChild(DataTableDirective, {static: false})
datatableElement: any = DataTableDirective;
min: any = 0;
max: any = 0;

Next, we use the custom function for filtering in our ngOnInit:

ngOnInit(): void {
  ...

  $.fn.dataTable.ext.search.push((settings: any, data: string[], dataIndex: any) => {
    const id = parseFloat(data[0]) || 0; // use data for the id column
    return (Number.isNaN(this.min) && Number.isNaN(this.max)) ||
        (Number.isNaN(this.min) && id <= this.max) ||
        (this.min <= id && Number.isNaN(this.max)) ||
        (this.min <= id && id <= this.max);
  });
}

This will get the max and min numbers, fetch the data, then update the data table. Next, we create a function to filter the data table by id:

filterById(): void {
  this.datatableElement.dtInstance.then((dtInstance: DataTables.Api) => {
    dtInstance.draw();
  });
}

Now it restarts the data table when we exit the page:

ngOnDestroy(): void {
  ...
  $.fn.dataTable.ext.search.pop();
}

With all this done, we then update our users.components.html page to initiate our filterById function:

<form (submit)="filterById()">
    <label>
        Min
        <input type="number" name="min" id="min" [(ngModel)]="min" />
    </label>
    <label>
        Max
        <input type="number" name="max" id="max" [(ngModel)]="max" />
    </label>
    <button class="btn btn-primary" type="submit">Filter by ID</button>
</form>
<br />

And that’s it — we can use custom filtering by id.

Buttons extension

As mentioned above, Angular DataTables supports a number of extensions, one of which is a buttons extension. The buttons extension allows us to export and copy our table data as a file. This is especially useful when we want to share data without giving access to the application.

To use the DataTables buttons extension, install its plugin using the below command:

# If you want to export excel files
npm install jszip --save
# JS file
npm install datatables.net-buttons --save
# CSS file
npm install datatables.net-buttons-dt --save
# Typings
npm install @types/datatables.net-buttons --save-dev

Then add the dependencies in the scripts and styles attributes:

{
  "projects": {
    "your-app-name": {
      "architect": {
        "build": {
          "options": {
            "styles": [
              ...
              "node_modules/datatables.net-buttons-dt/css/buttons.dataTables.css"
            ],
            "scripts": [
              ...
              "node_modules/jszip/dist/jszip.js",
              "node_modules/datatables.net-buttons/js/dataTables.buttons.js",
              "node_modules/datatables.net-buttons/js/buttons.colVis.js",
              "node_modules/datatables.net-buttons/js/buttons.flash.js",
              "node_modules/datatables.net-buttons/js/buttons.html5.js",
              "node_modules/datatables.net-buttons/js/buttons.print.js"
            ],
            ...
}

Then we include the configurations in our ngOnInit:

ngOnInit(): void {
  this.dtOptions = {
    // Declare the use of the extension in the dom parameter
    dom: 'Bfrtip',
  };
}

And here’s the result — the buttons Copy, Excel, CSV, and Print have been added:

Users Data Table with Buttons Added

There are many more options to choose from when it comes to customizing your data table. With a few tweaks, you can shape it to your specifications and it will come out perfect for whatever you’re building.

Wrapping up

And with that, we’ve introduced Angular DataTables and its features. We also applied it to an application, used some of its features, and explored the buttons extension. I made a few modifications to the original documentation because of the updates in Angular TypeScript. I hope this tutorial gave you a simple and easy-to-follow breakdown of how to use Angular DataTables in your Angular application.

Experience your Angular apps exactly how a user does

Debugging Angular applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking Angular state and actions for all of your users in production, try LogRocket. https://logrocket.com/signup/

LogRocket is like a DVR for web apps, recording literally everything that happens on your site including network requests, JavaScript errors, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.

The LogRocket NgRx plugin logs Angular state and actions to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.

Modernize how you debug your Angular apps - .

Kenneth Ekandem Software engineer with four years' experience in PHP and JavaScript. Currently working as a backend developer for Codekago Interactive.

3 Replies to “Using Angular DataTables to build feature-rich tables”

  1. Very useful, Thank you.
    How can we customize the language, from english to french as example ?
    Thanks

Leave a Reply