Creating an Angular2 Datatable from Scratch

Some time ago I’ve posted a tutorial on how to create a datatable with ag-grid, it didn’t take long before people start complaining that ag-grid wasn’t working the way I described in the tutorial, that’s because angular2 is changing rapidly rendering the component and/or the tutorial obsolete.

Today I’m going to show you again how to create a datatable, but this time I’m going to do it without ag-grid or any other third-party component, this is how our component will look like after we’re done:

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

That’s the simplest datatable structure I could come up with, as you can see we’re going to create two components: datatable and column.

Let’s take a look at the column component first:

import {Component, Input} from '@angular/core';
import {DatatableComponent} from './datatable.component';
 
@Component({
  selector: 'column',
  template: ``,
 
})
export class ColumnComponent {
	@Input() value;
	@Input() header;
 
	constructor(table: DatatableComponent) {
    	   table.addColumn(this)
  	}
}

This component has two attributes as inputs: value and header.

Value: This is the name of the attribute from your JSON dataset that will be displayed on this column (I’m going to talk about the dataset in a minute).
Header: As the name suggests, this is the column header text.

Besides these two attributes, there’s also the constructor, which very conveniently injects the DatatableComponent, allowing us to add this column to an array from the parent component. To fully understand why I’m doing this we have to take a look at the DatatableComponent:

import {Http, Response} from '@angular/http';
import {Injectable, Component, Input} from '@angular/core';
import {ColumnComponent} from './column.component';
 
@Component({
  selector: 'datatable',
  template: `<table>
               <thead>
                 <tr>
                   <th *ngFor="let column of columns">{{column.header}}</th>
                 </tr>
               </thead>
	       <tbody *ngFor="let row of dataset">
	  	 <tr>
	  	   <td *ngFor="let column of columns">{{row[column.value]}}</td>
	         </tr>
	       </tbody>
  	     </table>
  `
})
export class DatatableComponent { 
 
  @Input() dataset;
  columns: ColumnComponent[] = [];
 
  addColumn(column){
    this.columns.push(column);
  }
}

In this component we have the attribute dataset as an input (which will receive the JSON dataset) and the array of columns I just mentioned, each column will add itself to this array as we’ve seen on the ColumnComponent‘s constructor. In the template I’m iterating over both the dataset (rows) and the columns to create a regular HTML table.

After creating these two components we can use the datatable as I showed in the beginning, here is the app.component.ts:

import {Http, Response} from '@angular/http';
import {Injectable, Component } from '@angular/core';
 
@Component({
  selector: 'my-app',
  template: `<datatable [dataset]=cities>
                  <column [value]="'id'" [header]="'Id'"></column>
                  <column [value]="'city'" [header]="'City'"></column>
                  <column [value]="'country'" [header]="'Country'"></column>
             </datatable>
             `,
 
})
export class AppComponent { 
    cities;
 
    constructor(private http:Http) {
        this.http.get('data/cities.json')
                .subscribe(res => this.cities = res.json());
    }
}

Note that in the constructor I’m loading my dataset from the file cities.json, for more datails about that click here.

We’re almost done, the last thing we have to do is to declare our components in the app.module.ts:

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule }      from '@angular/http';
import { AppComponent }   from './app.component';
import {DatatableComponent} from './datatable.component';
import {ColumnComponent} from './column.component';
 
@NgModule({
  imports:      [ BrowserModule, HttpModule ],
  declarations: [ AppComponent,DatatableComponent, ColumnComponent],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

That’s it for now guys! Click here to see the part 2 of this tutorial where I’m showing how to add the filter functionality, if you need other specific features please let me know in the comments, any suggestions are welcome!

Recommended for you

7 comments on “Creating an Angular2 Datatable from Scratch

  1. Xin

    Hi, in the table component, for the line as below in the template

    {{row[column.value]}}

    what if I want to pass the row data to the column template component?

  2. Miguel Rico

    Hey this is awesome! and it works great! but I don’t really know…why/how it’s working.

    What is this process called? A component ‘swallowing’ another component like that?

    I didn’t even know you could pass a component through the constructor like that…man there is so much for me to learn!

    Thanks for posting this really helped out!! If you could help me out with my question just so I can go and educate my self, that would be great!

  3. Phuc

    Hi Leonardo,

    Thanks for sharing. I have 1 question about dynamic content template for columns. E.g: if column.value is a link or image source, I want to pass html link anchor or image …. how can I do that ?

    Thanks,

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