How to configure a reporting dashboard with Highcharts and Flexmonster in Angular

Highcharts and FM

 

In this start-to-finish tutorial, you’ll learn how to create an Angular application with interactive reporting functionality. As data visualization tools, you’ll use Highcharts – a multi-platform charting library, and Flexmonster Pivot – a JavaScript component that takes raw data, processes and displays it on the pivot grid. Combined together, tabular and charting visualizations make up an advanced analytics dashboard.

This tutorial is a perfect opportunity for you to master both data visualization and Angular development skills.

Here are a few practical reasons to complete this tutorial:

  • You’ll learn how to build a dynamic reporting app that relies on high-level data visualization components.
  • The resulting project will allow its end-users to dig into data in real-time and perform self-service analytics.

Prerequisites

To successfully walk through this tutorial, install the following tools on your machine:

  • A local development environment for Node.js.
  • The Angular CLI.

Pick the IDE of your choice, e.g., Visual Studio Code.

Preparing data

Instead of using theoretical data, you’ll be working with empirical data. Namely, you’ll set up a reporting dashboard to explore the COVID pandemic trends through interactive visualizations.

You can use any other data set interchangeably. But note that in this case, you should adjust your report’s structure according to your data sets’ field names.

Here’s a list of data sets we’ve chosen so far:

  • Data with the cumulative count of confirmed, death, and recovered cases of COVID-19 from different countries from 22nd January 2020 provided by Johns Hopkins University (covid_19_clean_complete.csv). It can be used for exploring the temporal dynamics of cases in the USA or other countries.
  • Data with confirmed cases in the USA provided by Johns Hopkins University (johns_hopkins_csse/2019-novel-coronavirus-covid-19-2019-ncov-data-repository-confirmed-cases-in-the-us.csv). It can be used to track the overall number of cases by states.

You can download the given data files to reproduce the results shown in this tutorial. All the data sets are open for research and freely available on the Kaggle platform.

Storing data

Let’s decide how the dashboard should access the data.
Let’s create a data folder within the src/assets directory where we will store the CSV data files.

Thinking through data visualization ideas

The main goal is to focus on the daily/weekly/monthly COVID dynamics in the United States. To achieve that, the dashboard will consist of multiple data visualization components:

  • Two pivot tables that aggregate data from different data sources.
  • A choropleth map that shows the number of confirmed cases in each state.
  • A bubble chart for reporting the number of active & recovered cases in different countries.
  • A line graph for reporting biweekly/weekly/monthly dynamics of cases in the USA.

Ready? Bring your data to life!

Establishing a project

First things first, create a new Angular project using the Angular CLI:

ng new reporting-app

Navigate to the workspace directory and launch the app:

cd reporting-app
ng serve --open

If everything is set up correctly, you should see the standard Angular app layout with a logo.

Installing Highcharts modules

Install the Highcharts package into your app:

npm install highcharts --save

Installing Flexmonster modules

Install the Flexmonster Angular module with a single npm command:

npm install ng-flexmonster

Open src/app/app.module.ts, import FlexmonsterPivotModule and add it to the imports array:

import { FlexmonsterPivotModule } from 'ng-flexmonster';
@NgModule({
  ...
  imports: [FlexmonsterPivotModule],
  ...
})

To allow Flexmonster to pass the summarized data to Highcharts, open angular.json and include the pivot table’s connector for Highcharts to the project’s scripts:

"scripts": [
  "node_modules/flexmonster/lib/flexmonster.highcharts.js"
]

Import the pivot table’s styles to src/styles.css:

@import "flexmonster/flexmonster.min.css"

Open app.component.ts and import flexmonster and ng-flexmonster TypeScript modules here:

import * as Flexmonster from 'flexmonster';
import { FlexmonsterPivot } from 'ng-flexmonster';

Creating a dashboard’s component

Since components are fundamental building blocks of Angular, let’s follow the component-oriented approach and create a separate component for your future dashboard. For this, create a dashboard folder inside the src/app directory. Next, create three files in this folder:

  • Dashboard.component.ts: to implement all the logic of configuring the pivot tables and charts and the interaction between them.
  • Dashboard.component.html: to describe how the dashboard’s component is rendered on the page.
  • Dashboard.component.css: to contain the component’s styles.

Open dashboard.component.ts and import Flexmonster and Highcharts modules:

import { Component, OnInit, ViewChild } from '@angular/core';
import { FlexmonsterPivot } from 'ng-flexmonster';
import * as Highcharts from 'highcharts';

Also, import Highcharts module for maps:

const HC_map = require("highcharts/modules/map");
HC_map(Highcharts);
require("./js/usamap")(Highcharts);

To create maps, add a js folder in the src/app/dashboard and place the usamap.js script. You can find its code here.

Define a component decorator for the class and provide configuration metadata to it:

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})

Angular needs the list of the directives used in the template as well as the template to be able to render them. To achieve that just define the template externally by providing its URL in templateUrl.
Next, create an exported class:

export class DashboardComponent implements OnInit {
}

Define two pivot table instances within the class declaration:

@ViewChild("pivot") pivot: FlexmonsterPivot;
@ViewChild("pivot2") pivot2: FlexmonsterPivot;
ngOnInit(): void {}

You need to create corresponding pivot tables reports to populate the pivot tables with data. The report is an object that contains information about a data source and describes the fields visible on the grid as well as applied filtering, sorting, formatting, etc.
Here’s a sample of how you can define a simple report for the pivot table:

public pivotReport = {
  dataSource: {
    filename: "./assets/data/covid_19_clean_complete.csv"
  },
  slice: {
    rows: [{
      uniqueName: "Date",
      filter: {
        query: {
          last: "month",
        },
      },
    }, ],
    columns: [{
        uniqueName: "Country/Region",
        filter: {
          members: ["country/region.[us]"],
        },
      },
      {
        uniqueName: "[Measures]",
      },
    ],
    measures: [{
        uniqueName: "Active",
        aggregation: "sum",
      },
      {
        uniqueName: "Recovered",
        aggregation: "sum",
      }
    ],
  },
};

Notice how we connected the pivot table to the data – by specifying the path to the file as a value of the filename property in the dataSource object.
You can experiment with measures, aggregations, fields depending on the insights you want to get.
See the exact configurations of the first and second reports.

Creating charts

Since the charts depend on the aggregated data from the pivot table, the table itself should be finished with data processing and rendered before the charts are created.
To track this moment, we’ll create handlers for the pivot’s reportcomplete event and attach them later when creating the component’s template in dashboard.component.html:

  onFirstReportComplete(): void {
    this.pivot.flexmonster.off("reportcomplete");
    this.createLineChart();
    this.createBubbleChart();
  }

  onSecondReportComplete(): void {
    this.pivot2.flexmonster.off("reportcomplete");
    this.createMap();
  }

Once the report has completed loading, we’ll draw charts that visualize the data from the pivot tables.

For example, here’s how you can define a function that’s responsible for drawing a line chart:

createLineChart(): void {
  this.pivot.flexmonster.highcharts.getData({
      type: "line",
    },
    function(chartConfig) {
      Highcharts.chart(
        "linechart-container", < Highcharts.Options > chartConfig
      );
    },
    function(chartConfig) {
      Highcharts.chart(
        "linechart-container", < Highcharts.Options > chartConfig
      );
    }
  );
}

We are using flexmonster.highcharts.getData() API call to fetch the data from the table and pass it to the chart in a ready-to-show format. This method is a part of the Connector for Highcharts. The main parameters it accepts are the type of the chart to prepare data for, the slice of data to visualize (optional), callback, and update handlers that are run when the pivot table is created and updated accordingly.
In the same way, you can create multiple functions that draw different charts, e.g., createLineChart(), createBubbleChart(), createMap(), etc.

Creating a component’s template

Open dashboard.component.html and define how visualization components should be positioned. Use the fm-pivot directive for the table and the div containers for charts.

<fm-pivot #pivot [toolbar]="true" [width]="'100%'" [height]="500" [report]="pivotReport" (reportcomplete)="onFirstReportComplete()">
</fm-pivot>
<fm-pivot #pivot2 [toolbar]="false" [width]="'100%'" [height]="500" [report]="reportUSA" (reportcomplete)="onSecondReportComplete()">
</fm-pivot>
<div id="linechart-container"></div>
<div id="bubblechart-container"></div>
<div id="map-container"></div>

Here you embed the pivot table and the containers for the charts. You can define as many components as you need. Make sure they all have unique identifiers.

(reportcomplete)="onFirstReportComplete()" – this line of code means if this event reportcomplete is fired, the onFirstReportComplete function is invoked.

Pay attention to the way the handlers of reportcomplete are attached. Events have to be enclosed in parentheses while all input properties have to be enclosed in square brackets. Read more about the input properties and events of the pivot table in its API reference.
Open app.module.ts, and import the dashboard component here:

import { DashboardComponent } from './dashboard/dashboard.component';

Add DashboardComponent to the declarations array to notify Angular which components belong to this module.

@NgModule({
  ….
  declarations: [AppComponent, DashboardComponent],
  ….
})

Configuring routing

To be able to navigate to the dashboard from the main page, establish a routing module. In src/app create the app-routing.module.ts file:

import {
  NgModule
} from "@angular/core";
import {
  RouterModule,
  Routes
} from "@angular/router";
import {
  DashboardComponent
} from "./dashboard/dashboard.component";

const appRoutes: Routes = [{
    path: "dashboard",
    component: DashboardComponent
  },
  {
    path: '**',
    redirectTo: 'dashboard'
  }
];

@NgModule({
  imports: [RouterModule.forRoot(appRoutes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

In app.component.html, add the RouterOutlet directive:

<router-outlet></router-outlet>

In app.module.ts, import the routing module:

import { AppRoutingModule } from "./app-routing.module";

Add the module to the imports array:

@NgModule({
  ....
  imports: [BrowserModule, FlexmonsterPivotModule, AppRoutingModule],
  ....
})

Styling the dashboard

Once you’re done with the dashboard’s layout, let’s take care of colors and fonts. For example, you can use the Roboto font and the following colors for charts: “#00A45A”, “#DF3800”, “#FFB800”, “#6D3BD8”, “#0075FF”. You can learn more about how to apply custom themes to the charts.

Results

Let’s run the app once again and see our new web analytics solution:

ng serve

Open http://localhost:4200/ or http://localhost:4200/dashboard:

Looks pretty good, isn’t it?

Conclusion

So, what have you got as a result?

Now you have a simple Angular application empowered with a reporting dashboard. The Flexmonster Pivot serves as an engine of our dashboard, thereby handling all the data processing and passing the ready-to-show data to the charts. Highcharts highlights important aspects of data with interactive graphs.

You’re ready to start delivering the app to your end-users. The main app benefit is that everyone can interact with it, save reports, and gain their unique insights. This is what distinguishes this dashboard from static reporting solutions.

Code & live demo ?

For demo purposes, the code is provided in its shortened version. Only the main highlights are given. See the full code of the Angular dashboard on GitHub.

Remarks ?

This article presents a general approach to creating a dashboard in Angular. You can customize it according to your own needs and objectives. You can also use the given approach when working with other front-end frameworks.

Also, this article is an example of how you can perform analytics; note that we’re using the latest available data at the moment of writing. The insights might not be entirely relevant at the time of reading this article.

In other words, the data is static. If you want to feed the dashboard with real-time updated data, consider using a database and a server-side solution for working with the pivot table.