Creating an Angular 2 chart component with FusionCharts

I have used FusionCharts for both Angular 1 and Angular 2 projects and have been happy with the results.  FusionCharts is a comprehensive JavaScript charting library, with 90+ charts. In this post I show how I created an Angular 2 chart component that depicts an investment analyst return line chart shown below.

This post assumes you have Angular 2 installed, you can get more information here.  You can download FusionCharts and the Angular 2 FusionCharts plug in here.  Once the plug in is downloaded follow the quick start to install and Import angular2-fusioncharts in the root NgModule.

Now we are ready to create the chart component.  Components are the building blocks of any Angular 2 application. They are blocks of reusable code consisting of a view, and some logic.

Here’s the basis of our chart component:

import { Component, Input, OnInit, OnChanges } from 'angular/core'; import { PerformanceService } from './../services/performance.service';

Component({ < em > selector: 'return-chart', < em > templateUrl: 'return-chart.component.html' < em >})

export class ReturnChartComponent {    dataSource: any;    errorMessage: string;    isBusy: boolean = false;    returns: any;    chartDef: any = {"paletteColors": "#0075c2,#1aaf5d,#006400","bgcolor": "#ffffff","labelDisplay": "rotate","slantLabels": "1",};

  constructor(private performanceService: PerformanceService) {}

  Input('inputData') inputData: any;

   ngOnChanges(changes: any) {         if (this.inputDat) {this.getData(this.inputData);}    }

   getData(inputData: any): void {}

    createChartData(chartData: any, seriesName: string): void {} }

If we look at what’s going on we first import needed modules and define the components properties selector and templateURL.  The selector is a css selector that identifies this component in a template and the templateUrl is a url to an external file containing a template for the view.

The Class method is where we add behavior and event bindings for the template.  Inside the class we first define needed variables, the chart definition could be kept in a separate file but since this component only job is to show the line chart I kept the definition with the component.

We now define the constructor injecting any needed services in our case the performance service.  We now need a way pass data into our component we can import the Input decorator from the Angular code, and decorate our property ‘inputData’.  The decorator tells angular to treat ‘inputData’ as an input binding.

We use the onChange lifecycle hook to detect any changes to ‘inputData’ and if it is changed to a non-null value getData is called passing ‘inputData’.  The getData() function will be dependent on your situation in my case I use a promise to call a services that calls a rest api to retrieve the requested data.

getData(inputData: any): void {    if (inputData && inputData.id) {       this.returns = null;       var that = this;       this.performanceService.getPerformanceData(inputData.id).subscribe(performance => {       if (performance && performance.length > 0) {               that.returns = performance;               that.createChartData(performance, inputData.name);        }    },    error => {    that.errorMessage = 'Error: GetData(): ' + <any>error;});   } }

Once the data is retrieved we are ready to format the data to be utilized by FusionCharts to render the chart.

createChartData(chartData: any, seriesName: string): void {       var ds = { chart: this.chartDef, categories: [], dataset: [] };       var category: any = [];       var series1: any = { seriesname: seriesName, data: [] };       var series2: any = { seriesname: 'Benchmark', data: [], visible: '0' };       for (let item of chartData) {              var tooltext = 'Custom Tool Tip';               category.push({ label: moment(item.positionDate).format('MM/DD/YYYY') });               series1.data.push({ value: item.Return, tooltext: tooltext });               series2.data.push({ value: item.bmReturn, tooltext: tooltext });        }       ds.categories.push({ category: category });       ds.dataset.push(series);       ds.dataset.push(series2);       setTimeout(() => { this.dataSource = ds }); }

FusionChart  expects the datasource to be an object defined as { chart: {}, categories: [], dataset: [] }.  Where chart is the chart definition, categories are the date labels for the x axis and dataset contains the series of data.   The above function loops through the data to create the charts datasource.  There are many option that you can do to customize your chart one of which is a custom tooltip.  We use setTimout to trigger change detection.

We also need to update app.module to declare our component.

Now that we created the charts datasource it time to render the chart.

In the components definition, we defined the templateUrl as 'return-chart.component.html'.

Inside this html file we have:

  <div id="returnChart">                 <fusioncharts width="100%" height="300"                               type="msline"                               dataFormat="json"                               [dataSource]=dataSource>                 </fusioncharts>    </div>

We create a div container make sure to set the element id so FusionChart can find where to render the chart.  The arguments we are passing include:

  • width and height: the chart dimensions
  • type: the type of chart we wish to create
  • dataFormat: the format of data passed to the dataSource option
  • dataSource: the configuration for the actual chart, as well as the data it should display

 

We have now created the chart component.  How do we utilize it?

<div id="AnalystChart"><return-chart [inputData]="analystData"></return-chart></div>

Using the defined selector we can drop this chart component any place you would like.

I hope this was informative and this is just the tip of the iceberg a lot more can be done using both Angular 2 and FusionCharts please refer to the documentation and see what you can do.

 

 

Let's discuss your project .... Give us a call or drop us a line