Skip to content
Angular ng libraries 4 min read

ngx-charts

ngx-charts is a charting library built specifically for Angular on top of D3. Instead of imperatively wiring up SVG and scales yourself, you describe charts declaratively in your templates with components like <ngx-charts-bar-vertical> or <ngx-charts-line-chart>, binding plain data and options. It handles the heavy lifting — D3 scales, axes, legends, tooltips, animations, and responsive resizing — while giving you Angular-native inputs, outputs, and ng-template customization. This makes it a natural fit when you want common chart types that look good out of the box and integrate cleanly with Angular’s change detection and signals.

Installing ngx-charts

ngx-charts depends on D3, which is installed alongside it. The ng add schematic registers the package and the required browser animations provider in one step.

ng add @swimlane/ngx-charts

If you prefer to install manually, add the package and ensure animations are provided in your application config.

Output:

✔ Package information loaded.
The package @swimlane/[email protected] will be installed and executed.
UPDATE package.json
UPDATE src/app/app.config.ts (added provideAnimations)
// src/app/app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideAnimations } from '@angular/platform-browser/animations';

export const appConfig: ApplicationConfig = {
  providers: [provideAnimations()],
};

ngx-charts relies on Angular’s animations module for its enter/update transitions. If provideAnimations() is missing, charts still render but without animated transitions and you may see runtime errors on some chart types.

Rendering your first chart

ngx-charts exposes standalone components, so you import only the chart you use. Data is supplied as an array of { name, value } objects (or series objects for multi-series charts). The example below uses signals for the data and a colorScheme object that ngx-charts maps onto its D3 color scales.

import { Component, signal } from '@angular/core';
import { BarChartModule } from '@swimlane/ngx-charts';

@Component({
  selector: 'app-traffic-chart',
  standalone: true,
  imports: [BarChartModule],
  template: `
    <ngx-charts-bar-vertical
      [results]="data()"
      [scheme]="scheme"
      [xAxis]="true"
      [yAxis]="true"
      [showXAxisLabel]="true"
      [showYAxisLabel]="true"
      xAxisLabel="Day"
      yAxisLabel="Visitors"
      [animations]="true"
      (select)="onSelect($event)"
    />
  `,
  styles: `:host { display: block; height: 400px; }`,
})
export class TrafficChartComponent {
  readonly scheme = { domain: ['#3b82f6', '#6366f1', '#8b5cf6'] };

  readonly data = signal([
    { name: 'Mon', value: 4200 },
    { name: 'Tue', value: 5100 },
    { name: 'Wed', value: 3900 },
    { name: 'Thu', value: 6400 },
    { name: 'Fri', value: 7300 },
  ]);

  onSelect(event: { name: string; value: number }): void {
    console.log('Clicked bar:', event.name, event.value);
  }
}

Output:

Clicked bar: Thu 6400

The chart sizes itself to its container, so giving the host element an explicit height (as above) is essential — without a sized parent, the SVG collapses to zero height.

Common chart types

Each chart type is its own component with a focused set of inputs. Multi-series charts (line, area, grouped/stacked bar) expect a nested series array rather than flat values.

ChartComponentData shape
Vertical barngx-charts-bar-vertical{ name, value }[]
Grouped barngx-charts-bar-vertical-2d{ name, series: { name, value }[] }[]
Linengx-charts-line-chart{ name, series: { name, value }[] }[]
Areangx-charts-area-chart{ name, series: { name, value }[] }[]
Pie / donutngx-charts-pie-chart{ name, value }[]
Heat mapngx-charts-heat-map{ name, series: { name, value }[] }[]

A multi-series line chart consumes the nested shape directly:

import { Component, signal } from '@angular/core';
import { LineChartModule } from '@swimlane/ngx-charts';

@Component({
  selector: 'app-revenue-chart',
  standalone: true,
  imports: [LineChartModule],
  template: `
    <ngx-charts-line-chart
      [results]="series()"
      [legend]="true"
      [xAxis]="true"
      [yAxis]="true"
      [autoScale]="true"
    />
  `,
  styles: `:host { display: block; height: 400px; }`,
})
export class RevenueChartComponent {
  readonly series = signal([
    {
      name: '2025',
      series: [
        { name: 'Q1', value: 120 },
        { name: 'Q2', value: 180 },
        { name: 'Q3', value: 150 },
        { name: 'Q4', value: 210 },
      ],
    },
    {
      name: '2026',
      series: [
        { name: 'Q1', value: 160 },
        { name: 'Q2', value: 200 },
        { name: 'Q3', value: 240 },
        { name: 'Q4', value: 300 },
      ],
    },
  ]);
}

Customizing tooltips and labels

Most charts accept projected ng-template content for tooltips and labels, letting you render arbitrary Angular markup with the chart’s context. Use the appropriate template reference — tooltipTemplate for the hover tooltip on bar charts, for example.

<ngx-charts-bar-vertical [results]="data()" [scheme]="scheme">
  <ng-template #tooltipTemplate let-model="model">
    <div class="tip">
      <strong>{{ model.name }}</strong>
      <span>{{ model.value | number }} visitors</span>
    </div>
  </ng-template>
</ngx-charts-bar-vertical>

You can also format axis ticks with a function bound to [xAxisTickFormatting] or [yAxisTickFormatting], which keeps formatting logic in your component:

formatThousands = (value: number): string => `${value / 1000}k`;

Pass [animations]="false" for charts that re-render frequently (such as live dashboards). Replaying D3 enter animations on every data tick is expensive and causes visible flicker.

Best Practices

  • Always give the chart’s host or wrapper element an explicit height; ngx-charts measures its container and renders nothing useful inside a zero-height box.
  • Replace the whole signal/array reference when updating data so Angular’s change detection and ngx-charts’ diffing pick up the change — mutating the existing array in place may not trigger a redraw.
  • Import only the specific chart module (BarChartModule, LineChartModule, etc.) rather than NgxChartsModule to keep bundles small and tree-shakeable.
  • Define color schemes as a stable { domain: string[] } object reference (a class field) instead of an inline object literal in the template to avoid needless re-renders.
  • Disable animations on high-frequency real-time charts, and prefer [autoScale]="true" for clearer axes on data that does not start at zero.
  • Use ng-template customization for tooltips and labels instead of forking the library when the defaults do not match your design system.
Last updated June 14, 2026
Was this helpful?