Creating an Angular2 Datatable from Scratch PART 2: Filtering the Data

Continuing from where we stopped at Part 1, today we’re going to add the filter functionality to the table, but before we start let’s do some styling. I’m going to use Bootstrap, but if you don’t want you don’t have to, feel free to style your component as you like. But if you decide to use Bootstrap as well you’ll have to add these scripts to your index.html:

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" >
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" ></script>

Now I’m going to add the class table to the table element in the DatatableComponent, this class will make the grid look like this:

Table With Bootstrap Style
Table With Bootstrap Style

It looks so much better already! Now let’s get started with the filter, most of the modifications will be made on the datatable.component.ts file, here’s the component after the changes:

import {Http, Response} from '@angular/http';
import {Injectable, Component, Input} from '@angular/core';
import {ColumnComponent} from './column.component';
 
@Component({
  selector: 'datatable',
  template: `
      <input type="text" class="form-control" *ngIf=enableFilter [(ngModel)]=query 
         (keyup)=filter() placeholder="Filter" />
      <table class="table">
        <thead>
          <tr>
            <th *ngFor="let column of columns">{{column.header}}</th>
          </tr>
        </thead>
        <tbody *ngFor="let row of getData()">
	  <tr>
	    <td *ngFor="let column of columns">{{row[column.value]}}</td>
	  </tr>
        </tbody>
      </table>
  `
})
export class DatatableComponent { 
 
  @Input() dataset;
  @Input() enableFilter = false;
  columns: ColumnComponent[] = [];
  query = "";
  filteredList;
 
  addColumn(column){
    this.columns.push(column);
  }
 
  getData(){
    if(this.query !== ""){
      return this.filteredList;
    }else{
      return this.dataset;  
    }
  }
 
  filter(){
    this.filteredList = this.dataset.filter(function(el){
      var result="";
        for(var key in el){
          result+= el[key];
        }
        return result.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
    }.bind(this));
  }
}

Let’s start by talking about the new attributes:

enableFilter: This is an input that indicates weather the filter is going to be enabled or not, it’s false by default.
query: Variable that stores the filter typed by the user.
filteredList: This variable is going to store the new dataset after the filtering, it’s necessary to use a different array in order to preserve the original data.

Now the new functions:

filter(): Function responsible for filtering the data when the user types something on the input, it’ll filter the data from the dataset variable and assign the result to the filteredList.
getData(): Our table will work simultaneously with two arrays, the dataset and filteredList, this function is responsible for telling which one will be used at any given moment, if the table has filtered data to show it’ll use the filteredList otherwise it’ll use the dataset.

Besides the new attributes and functions I’ve also modified the template a little bit, in the tbody I’ve change the ngFor from let row of dataset to let row of getData(), and as you can see there is an input above the table where the user can type, it’ll call the filter() function on the keyup event and it’ll only be visible when the enableFilter is true (For this input to work we also have to import the FormsModule on the app.module.js).

Now your datatable can be used like this:

<datatable [dataset]=cities [enableFilter]=true >
      <column [value]="'id'" [header]="'Id'"></column>
      <column [value]="'city'" [header]="'City'"></column>
      <column [value]="'country'" [header]="'Country'"></column>
 </datatable>

The only thing that has changed is that now we have the option enableFilter that will render an input above the table when set to true.

Recommended for you

Angular2: How to Pass Callback Functions to a Component There are lots of situations where it's useful to pass a function to an angular2 component, for instance, when our component is a dialog and we have to perform an specific task when it closes, or pass the action of one of its buttons, or even events like keypress, resize, mouseover, etc. If you're r...
Creating a Live Auction App with Angular 2, Node.js and Socket.IO Angular 2 Auction App In this tutorial we're going to build a very cool Live Auction Application, my goal is to demonstrate how Angular 2, Node.js and Socket.io work together, and as everyone knows Angular 2 will soon come out so I thought it would be great to write a tutorial involving it. Of c...
Angular 2 Tutorial: Adding HotKeys (Keyboard shortcuts) to a Component Arguably hotkeys can substantially increase the usability of an application, the less the users have to touch the mouse the better will be their experience with the application. Luckily for us there is a very easy way of defining hotkeys on angular2, which is by adding a listener to the host comp...
Angular2 Tutorial: Detecting Clicks Outside the Component Angular2 click detection Sometimes there is a need to detect whether the user is clicking inside or outside our angular2 component, specially if your component has a dropdown element, in this case you need to know exactly where the click occurred in order to perform the right action. In this tut...

6 comments on “Creating an Angular2 Datatable from Scratch PART 2: Filtering the Data

  1. willfrench

    This is a great tutorial! I am confused though, as to why the *ngFor for the rows is in the tbody element (and not in the tr element). I’m a bit new to ng so it’s quite possible I’m missing something obvious.

  2. Richard

    Great post! Just a question.. If I have my JSON like:

    “city”:”Rome”,
    “country”:”Italy”,
    “address”:{
    “street”:”main street”,
    “number”:”1000″
    }

    How I show the street line in the table?

    Thank You!

  3. Mike

    Using your example, how would I pass in a html obj into that’s not in the json?

    For example:
    {{row[column.value]}} = “url”

    And I want to create link text as a

    Thanks!

Leave a Reply to willfrench 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>