Charts with Angular: ngx-charts (Formerly: ng2d3)

Originally, I wanted to write an article about ng2d3. That’s a fine library bringing the power of D3.js charts to the Angular2 world without the price. D3 requires you to adopt a special programming style. You have to learn and use a new programming paradigm, the data-driven programming style. ng2d3 doesn’t require such a thing. You just pass it the data, and it’ll draw the diagram for you.

The only problem with ng2d3 is that it doesn’t exist anymore. More precisely, when I started writing, the team published a new major version (including a couple of breaking changes) and changed the name of the project. Now it’s called ngx-charts. In the view of the new semantic versioning strategy of Angular, the name makes a lot of sense. Calling a framework “ng2-something” won’t work when Angular4 will have been published, skipping Angular3 altogether.

The new name makes even more sense in that it focuses on charts, not on a particular framework to generate charts. D3.js may be the basis of ngx-charts, but it’s both famous and dreaded for its particular approach to drawing charts. I’ve already mentioned the data-driven approach. Plus, using D3.js amounts to care about every aspect of your chart. If you need such a simple thing as an x-axis, you have to write several lines of code for it. That’s not the declarative approach most people prefer.

By the way, I should mention that learning D3 is worth the trouble. Once you’ve understood how D3.js works, you can generate awesome animated and interactive graphics.

What makes ngx-charts different from using D3 directly

Nonetheless, the nice thing about ngx-charts is that it allows you do draw charts in a more traditional way. You pass your chart data to the library, and that’s all you have to do. ngx-charts adds all the small details, including legends, tool-tips, call-backs for user interaction and even some animations.

What makes ngx-charts different from other Angular chart libraries

Before finding ngx-charts, I’ve also tested a couple of other chart libraries. They aren’t bad, but in my eyes, ngx-chart has an edge with respect to features and flexibility. For instance, the one feature we needed isn’t supported by any library I’ve tested: line charts which aren’t smooth but stepped. My business use case required this kind of charts, but even such a popular library as Valor Software’s ng2-chart insists on drawing smooth lines. ngx-charts gives you both options (and quite a few more).

Architecture of ngx-charts

Many chart libraries draw their charts in a canvas or in an SVG image that’s not linked to the life cycle events of Angular. As a consequence, many of these static images aren’t redrawn when the window size is changed. ngx-charts adds an interesting twist: it uses D3.js to do the math but leaves the actual drawing to Angular. This way, you’ve got the best of both worlds.

As it turns out, that sound’s more difficult than it is. The idea is simply to define the SVG elements as components. For instance, a radically simplified bar chart looks like so:

@Component({
  selector: 'g[ngx-charts-series-horizontal]',
  template: `
    <svg:path 
      *ngFor="let bar of bars"
      [attr.d]="path(bar.x, bar.y, bar.width, bar.height)" />
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  animations: [ ... ],
})
export class SeriesHorizontal implements OnChanges {
   path(x, y, width, height: number): String {
     return `M ${x} ${y} h ${width} v ${height}`;
   }
}

You’ll recognize the familiar building blocks of Angular. The SVG magic is generated as ordinary HTML code in the template. In this case, it’s an SVG path that’s repeated for every bar in the data set. The coordinates of the path are calculated in a function of the component. Usually, the gory details of the path definition are usually left to D3.js. But that’s a small price to pay for a decent integration with Angular.

Walkthrough

I had some difficulties starting with ngx-charts because the examples provided by the project don’t exactly match the project structure of the Angular CLI. To help you to get started, I’ve provided a minimal example at my GitHub repository. At the time of writing, there’s only one simple example (the line chart), and a complex example showing how to use the charts in a real-world application. Over time, I’ll add more examples if time allows. Just in case you’re confused by the weird class names: the complex example shows the fuel consumption of my last two cars, and I’ve derived the simple example from it.

I gather you’ve already got node.js, npm, and the latest Angular CLI installed. I also omit the steps that are well documented, pointing out only the project setup because that’s what proved to be difficult. To create the project, type this command on the command line:

ng new my-charts
cd my-charts

Next, you need to add ngx-charts and D3.js to your project:

ng g component consumption-component
npm install @swimlane/ngx-charts --save
npm install d3 --save
npm install @types/d3 --save-dev

At this point, the examples provided by the ngx-charts team seem to be a bit odd. They’re using a D3.d.ts file hidden (or exposed, depending on your point of view) in the node-modules folder of the ngx-charts project. I didn’t feel comfortable to use such a local resource, so I decided to use one of the official type definitions of D3. However, there’s no typings definition, so I had to use a @types definition. That, in turn, defines a couple of variables slightly differently. So you can’t simply copy the examples from the Plunker examples embedded in the documentation. Instead, you have to modify some of them. Cutting a long story short: probably you’re better off using the internal D3.d.ts of ngx-charts, which results in imports statements like

import d3 from '@swimlane/ngx-charts/release/d3';

Be that as it may, you also need to include a CSS file. The easiest way to do this is to add it to the angular-cli.json like so:

...
"styles": [
   "styles.css",
   "../node_modules/@swimlane/ngx-charts/release/ngx-charts.css"
],
...

The rest is more-or-less plain vanilla. You add the NgxChartsModule to your @NgModule:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    NgxChartsModule
  ],
  exports: [],
  bootstrap: [AppComponent]
 })
export class AppModule {
}

Basically, that’s all you need to know to use the examples of the ngx-charts documentation. I could list the HTML file and the Typescript file of the component, but they don’t add much information. Better import my demo project from GitHub into your IDE and start modifying it yourself.

Wrapping it up

If you just want to create a beautiful chart quickly without having to learn a lot of things first, I (currently) recommend ngx-charts. It integrates nicely with both Angular and D3.js, it’s pretty popular and the resulting charts look great. It’s a nice compromise between ease-of-use and a rich feature set.


Dig deeper

ngx-charts project page on GitHub
ngx-charts live demo
ngx-charts documentation

Leave a Reply

Your email address will not be published.