Reactive, responsive, beautiful charts for Angular based on Chart.js
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
The BaseChartDirective is the core component of ng2-charts that provides Angular integration for Chart.js. It supports 8 chart types with reactive data binding, event handling, and lifecycle management.
Angular directive that wraps Chart.js functionality with full TypeScript support and Angular lifecycle integration.
/**
* Angular directive for creating reactive charts using Chart.js
* Supports all Chart.js chart types with Angular data binding and events
*/
@Directive({
selector: 'canvas[baseChart]',
exportAs: 'base-chart',
standalone: true
})
export class BaseChartDirective<
TType extends ChartType = ChartType,
TData = DefaultDataPoint<TType>,
TLabel = unknown
> implements OnDestroy, OnChanges {
/** Chart type: 'line', 'bar', 'radar', 'pie', 'polarArea', 'doughnut', 'bubble', 'scatter' */
@Input() type: ChartConfiguration<TType, TData, TLabel>['type'];
/** Show/hide chart legend */
@Input() legend?: boolean;
/** Complete chart data structure (alternative to labels/datasets) */
@Input() data?: ChartConfiguration<TType, TData, TLabel>['data'];
/** Chart configuration options */
@Input() options: ChartConfiguration<TType, TData, TLabel>['options'];
/** Array of Chart.js plugins */
@Input() plugins: Plugin<TType>[];
/** Chart labels (used with datasets input) */
@Input() labels?: ChartConfiguration<TType, TData, TLabel>['data']['labels'];
/** Chart datasets (used with labels input) */
@Input() datasets?: ChartConfiguration<TType, TData, TLabel>['data']['datasets'];
/** Emits when chart is clicked */
@Output() chartClick: EventEmitter<{event?: ChartEvent; active?: object[]}>;
/** Emits when chart is hovered */
@Output() chartHover: EventEmitter<{event: ChartEvent; active: object[]}>;
/** Canvas 2D context */
ctx: string;
/** Chart.js instance */
chart?: Chart<TType, TData, TLabel>;
/**
* Constructor for BaseChartDirective
* @param element - ElementRef to the canvas element
* @param zone - NgZone for running outside Angular zone for performance
* @param themeService - ThemeService for dynamic theming
* @param config - Optional ng2-charts configuration
*/
constructor(element: ElementRef, zone: NgZone, themeService: ThemeService, config?: NgChartsConfiguration);
/** Lifecycle method called when input properties change */
ngOnChanges(changes: SimpleChanges): void;
/** Lifecycle method called when component is destroyed */
ngOnDestroy(): void;
}Usage Examples:
import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartData, ChartOptions, ChartType } from 'chart.js';
@Component({
template: `
<canvas
baseChart
[data]="lineChartData"
[options]="lineChartOptions"
[type]="'line'"
(chartClick)="onChartClick($event)">
</canvas>
`,
standalone: true,
imports: [BaseChartDirective]
})
export class LineChartComponent {
lineChartData: ChartData<'line'> = {
labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
datasets: [{
data: [65, 59, 80, 81, 56, 55, 40],
label: 'Series A',
fill: false,
tension: 0.5,
borderColor: 'rgb(75, 192, 192)',
backgroundColor: 'rgba(75, 192, 192, 0.2)'
}]
};
lineChartOptions: ChartOptions<'line'> = {
responsive: false
};
onChartClick(event: any) {
console.log(event);
}
}Creates or recreates the Chart.js instance.
/**
* Creates or recreates the Chart.js instance
* Destroys existing chart if present and creates a new one
* @returns The created Chart.js instance
*/
render(): Chart<TType, TData, TLabel>;Updates the chart with current data without full recreation.
/**
* Updates the chart with current data
* More efficient than render() for data changes
* @param mode - Chart.js update mode ('resize', 'reset', 'none', 'hide', 'show', 'normal', 'active')
*/
update(mode?: UpdateMode): void;Controls visibility of individual datasets within the chart.
/**
* Shows or hides a specific dataset
* @param index - Dataset index
* @param hidden - Whether to hide the dataset
*/
hideDataset(index: number, hidden: boolean): void;
/**
* Checks if a dataset is currently hidden
* @param index - Dataset index
* @returns True if hidden, false if visible, undefined if dataset doesn't exist
*/
isDatasetHidden(index: number): boolean | undefined;Exports the chart as a base64-encoded image.
/**
* Returns the chart as a base64-encoded PNG image
* @returns Base64 image string or undefined if chart not available
*/
toBase64Image(): string | undefined;Usage Example:
import { Component, ViewChild } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartData } from 'chart.js';
@Component({
template: `
<canvas #chart baseChart [data]="chartData" [type]="'bar'"></canvas>
<button (click)="exportChart()">Export Chart</button>
<button (click)="toggleDataset(0)">Toggle First Dataset</button>
`,
standalone: true,
imports: [BaseChartDirective]
})
export class ChartControlComponent {
@ViewChild('chart') chart!: BaseChartDirective;
chartData = {
labels: ['Red', 'Blue', 'Yellow'],
datasets: [{
label: 'Dataset 1',
data: [300, 50, 100]
}, {
label: 'Dataset 2',
data: [50, 250, 120]
}]
};
exportChart() {
const base64 = this.chart.toBase64Image();
if (base64) {
const link = document.createElement('a');
link.download = 'chart.png';
link.href = base64;
link.click();
}
}
toggleDataset(index: number) {
const isHidden = this.chart.isDatasetHidden(index);
this.chart.hideDataset(index, !isHidden);
}
}ng2-charts supports all standard Chart.js chart types:
interface ChartClickEvent {
event?: ChartEvent;
active?: object[];
}interface ChartHoverEvent {
event: ChartEvent;
active: object[];
}Event Usage Example:
import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartEvent } from 'chart.js';
@Component({
template: `
<canvas
baseChart
[data]="chartData"
[type]="'bar'"
(chartClick)="onChartClick($event)"
(chartHover)="onChartHover($event)">
</canvas>
`,
standalone: true,
imports: [BaseChartDirective]
})
export class InteractiveChartComponent {
onChartClick(event: {event?: ChartEvent; active?: object[]}) {
if (event.active && event.active.length > 0) {
console.log('Clicked on data point:', event.active);
}
}
onChartHover(event: {event: ChartEvent; active: object[]}) {
if (event.active.length > 0) {
console.log('Hovering over data point:', event.active);
}
}
}