Learning d3.js can be a steep learning curve. Having D3.js chart on Angular.js web apps can be tricky for developers new to the world of data visualisation. Certainly, this is what I found out recently when I tried to put together a line chart to display results from an AI data model. I found it quite tricky to get D3 and Angular working collectively.
In this blog, I’ll go step by step on how to include a line chart on an Angular web apps. I’m going to break the process into two steps:
- Import D3.js library on Angular
- Display a line chart on an Angular component
In this project, I’ll use Angular 7 and D3.js version 5, both of which — at the time of writing this blog — are the latest versions. Note that this blog is intended for developers new to d3.js and have some experience on Angular.js. If you’re a wizard in D3.js, then this blog is not for you. Feel free to read through, you never know you might pick up something new!
Import D3.js library on Angular
There is a d3 package available for Angular in npm. To install it, run npm install d3 on your terminal/console window.
The generated Angular project comes with a default component called app, which work as the higher level component. You are also able to create sub components. For my project, I have created a sub-component by running the following command:
ng g c LineChart
This command will generate a component with the name LineChart. It is a good practice to have each feature of your application as a separate component. Angular.js gives you that modularity.
Once you generated the new component, go to your root component html file: app.component.html, and reference the newly generated component to it by calling its selector: <app-line-chart></app-line-chart>. All the visualisation for the line chart will be with the two tags.
Now, import the d3 package on to the new component: import * as d3 from ‘d3’;
On your newly created Angular component you’ll see a function called ngOnInit(), within it where all the d3.js code will be.
Display a line chart on an Angular component
Before we start our visualisation we need to have our data in hand. Because without data, visualisation is meaningless. For this visualisation, I have a data.json file with list of entries, in each entry there are three fields: date, value1, value2 (see the data.json file in github).
In D3.js visualisation happens on top of SVG (Scalable Vector Graphics), which is technically an XML based markup language.
I created my SVG canvas and given it 1024*768 dimension. I also specified the margin for all four sides of the canvas.
I then selected the SVG canvas from the html. You can see the html in line-chart.component.html. Once the SVG is selected by its id tag, I given it a width and height and created a group tag inside it where the rest of the visualisation tags will be and moved it slightly from the top left corner.
In my dataset, date is in string format. D3 allows you to convert string to date format using the timeParse() function. Using forEach loop, I iterated through each entry and converted into the correct date format.
Once you have the data ready, you need to create the x and y-axis using the data. In my line chart, I have two y-axes. Since my x-axis based on date I’m using the scaleTime() function. For axes you need to specified the domain and range of your data. The nice() function is called to add bit extra space for the upper range of the chart so the highest point does not touch the top edge of the chart.
I have created two arrays to store names of the lines for each respective y-axis. And then iterated over each array and created the path for each line. This is an elegant way to add lines to the SVG, because if more lines needed to be added for each y axis, all is required is to add the name on to the array. Note that I have used d3.curveMonotoneX for the shape of the line, you can use other shapes — read the docs in https://github.com/d3/d3-shape#curveMonotoneX.
Now layout each axis on its respective place. On my chart, I have put each axis inside a group tag and gave it a class. This makes the layout in html lot easier to read and debug.
The process for adding label for each axis is quite similar, apart from its position — of course. To add a label, you need to grab the SVG and append the text and positioned at the correct place.
For a line chart, it is quite nice to show each data point to the user. The process of adding points is similar for both y axes. All you need is to get the property name for each line and loop through it for each data and append a circle to the line. I also added a tooltip for each point which shows the x and y value.
To add legend you first need to get the SVG and position it where you like it to be. Now go through each line of the chart and append a rectangle with the colour of the line and position it inside the legend box. Append the title next to each rectangle. Note that I added ellipses if the text is greater than 8 characters, this is to avoid text going beyond the legend box.
Having grids also makes it easier to map the points to the axes. Adding grids to x and y axis are similar. First, you need to specify the axis and the format of the grids. Then grab the SVG and append a group tap and insert the grids within.
For my line chart I have added a vertical reference line. Just like before, you need to grab the SVG and append the line with coordinates. Since it is a vertical line the x coordinates are same and the y coordinates are the min and max. Similarly, you can add horizontal line as well; just the coordinates need to the reversed. I have also styled the line using CSS for visualisation purpose.
When I run my angular app this is how the line chart looks like.