Highcharts and Angular 7

Logos of Angular and Highcharts

 

 

In this tutorial, I will show you how to use Angular 7 and Highcharts to create a simple web page that fetches data via an API and generates charts from it.

More specifically, we want our web page to render an interactive scatter chart displaying dates (timestamps) in chronological order along the x-axes and values for each timestamp along the y-axes. The entire project is saved in this GitHub link and here is the link to the dummy data.

I divided the tutorial into two main sections; the first section is about how to set up the project and the second one is about how to integrate Highcharts.

Let’s get started 🙂

Setup the project

The first thing to do is to install Angular CLI using this command line npm install -g @angular/cli. To be sure that the Angular CLI is well installed, I verify that I read the version, for example, ng --version

If there is no error, I am happy 🙂

Then create a folder for the project, enter it, and run the following command: ng new angular7-highcharts. Once done, go to the angular7-highcharts folder, then you can run the project using these ng serve.The application is running on http://localhost:4200/

For better organization, I created a component dedicated to the chart view using this command line ng generate component output-graph.

The new component, output-graph, is found under /src/app/ and consists of four different files:

  • .CSS: All CSS for styles should go into this file.
  • .HTML: This file includes HTML template and all HTML tags.
  • .TS: This file includes all typescript code, the business logic, API calls, and data manipulation.
  • .SPEC.TS:All unit tests go into this file.

Remark: I will not cover the Angular 7 unit tests, for those who don’t know it, since it is a topic that requires a tutorial of its own.

The last step in this section is to modify the “app component” according to the project’s need, by removing the extra default content from app/app.component.html and including my new component as:

<div id="main-head" style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <app-output-graph></app-output-graph>
</div>
<router-outlet></router-outlet>

app-output-graph is the selector of the new component. Now, I can add/modify the content of the parent component by changing variables i.e. title in the file app/app.component.ts as:

...
export class AppComponent {
  title = 'High Charts Simplified';
}

And finally, I style the parent component app/app.component.css file as:

#main-head{
  background-color: cornflowerblue;
  text-align: center;
}

Integrate Highcharts

Next, we want to focus on charting, using Highcharts. This step is simple and straightforward.

First, install the library using via the command line npm install highcharts.

Then, import the Highcharts library into the output-graph.component.ts, because, as mentioned above, all logic resides in the .ts files.

import { Component, OnInit } from '@angular/core';
import * as Highcharts from 'highcharts';

declare var require: any;
let Boost = require('highcharts/modules/boost');
let noData = require('highcharts/modules/no-data-to-display');
let More = require('highcharts/highcharts-more');

Boost(Highcharts);
noData(Highcharts);
More(Highcharts);
noData(Highcharts);

@Component({
  selector: 'app-output-graph',
  templateUrl: './output-graph.component.html',
  styleUrls: ['./output-graph.component.css']
})
export class OutputGraphComponent implements OnInit {
  public options: any = {
    chart: {
      type: 'scatter',
      height: 700
    },
    title: {
      text: 'Sample Scatter Plot'
    },
    credits: {
      enabled: false
    },
    tooltip: {
      formatter: function() {
        return 'x: ' + Highcharts.dateFormat('%e %b %y %H:%M:%S', this.x) +
          ' 
 y: ' + this.y.toFixed(2);
      }
    },
    xAxis: {
      type: 'datetime',
      labels: {
        formatter: function() {
          return Highcharts.dateFormat('%e %b %y', this.value);
        }
      }
    },
    series: [
      {
        name: 'Normal',
        turboThreshold: 500000,
        data: [[new Date('2018-01-25 18:38:31').getTime(), 2]]
      },
      {
        name: 'Abnormal',
        turboThreshold: 500000,
        data: [[new Date('2018-02-05 18:38:31').getTime(), 7]]
      }
    ]
  }
  constructor() { }

  ngOnInit(){
    Highcharts.chart('container', this.options);
  }
}

We are all set and may run the application with the command ng serve.
Whoaa! The application is displaying an interactive chart with two hard-coded points on it.

Before going any further, let’s take a look at how the Highcharts library works. For more details check the official API documentation.

  • chart includes the chart type.
  • Title includes chart title.
  • Tooltip has the tooltip’s customizations.
  • Series includes the data and categories of data. In this project, I am using normal and abnormal data generated from an AI (artificial intelligence data).

I am also using the method ngOnInit() that is a trigger to call the application to draw the chart inside a div element. The div element has an id equals to container with default settings as this.options.

…
ngOnInit(){
    Highcharts.chart('container', this.options);
  }
}

Now, let’s try to pull some data from an external source, using this API.

Let’s return to the .ts file again output-graph/output-graph.component.ts, then make the right modification to fetch the data from the API:

import { Component, OnInit } from '@angular/core';
import * as Highcharts from 'highcharts';
import { HttpClient } from '@angular/common/http';
import { interval, Subscription } from 'rxjs';

declare var require: any;
let Boost = require('highcharts/modules/boost');
let noData = require('highcharts/modules/no-data-to-display');
let More = require('highcharts/highcharts-more');

Boost(Highcharts);
noData(Highcharts);
More(Highcharts);
noData(Highcharts);

@Component({
  selector: 'app-output-graph',
  templateUrl: './output-graph.component.html',
  styleUrls: ['./output-graph.component.css']
})
export class OutputGraphComponent implements OnInit {
  public options: any = {
    chart: {
      type: 'scatter',
      height: 700
    },
    title: {
      text: 'Sample Scatter Plot'
    },
    credits: {
      enabled: false
    },
    tooltip: {
      formatter: function() {
        return 'x: ' + Highcharts.dateFormat('%e %b %y %H:%M:%S', this.x) +
          ' 
 y: ' + this.y.toFixed(2);
      }
    },
    xAxis: {
      type: 'datetime',
      labels: {
        formatter: function() {
          return Highcharts.dateFormat('%e %b %y', this.value);
        }
      }
    },
    series: [
      {
        name: 'Normal',
        turboThreshold: 500000,
        data: []
      },
      {
        name: 'Abnormal',
        turboThreshold: 500000,
        data: []
      }
    ]
  }
  subscription: Subscription;
  constructor(private http: HttpClient) { }

  ngOnInit(){
    // Set 10 seconds interval to update data again and again
    const source = interval(10000);

    // Sample API
    const apiLink = 'https://api.myjson.com/bins/13lnf4';

    this.subscription = source.subscribe(val => this.getApiResponse(apiLink).then(
      data => {
        const updated_normal_data = [];
        const updated_abnormal_data = [];
        data.forEach(row => {
          const temp_row = [
            new Date(row.timestamp).getTime(),
            row.value
          ];
          row.Normal === 1 ? updated_normal_data.push(temp_row) : updated_abnormal_data.push(temp_row);
        });
        this.options.series[0]['data'] = updated_normal_data;
        this.options.series[1]['data'] = updated_abnormal_data;
        Highcharts.chart('container', this.options);
      },
      error => {
        console.log('Something went wrong.');
      })
    );
  }

  getApiResponse(url) {
    return this.http.get(url, {})
      .toPromise().then(res => {
        return res;
      });
  }
}

To make this project more dynamic, let’s add this function getApiResponse(url) to call the API each 10 seconds to get fresh data. I also import HttpClientModule to initiate HTTP request and responses in angular apps:

...
import { HttpClientModule } from '@angular/common/http';
...
@NgModule({
  ...
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  ...
})

Ok, our application is complete now. Let’s run it again using this command line ng serve.

Congrats! If you have followed along, you’ve now created an Angular application with dynamic data bindings! I hope this project will help you to understand better how to build an Angular application and how to integrate the Highcharts library. Feel free to add your comment or question below; I will be happy to answer.