Angular でグラフを出すなら、Chart.js を Angular から使えるようにする ng2-charts が手早い方法です。 手順は3つです。

npm install ng2-charts chart.js
// app.config.ts:Chart.js の部品を登録する
providers: [provideCharts(withDefaultRegisterables())]
<!-- コンポーネント:imports に BaseChartDirective を入れて canvas に付ける -->
<canvas baseChart type="bar" [data]="data" [options]="options"></canvas>

データを変えてもグラフが変わらないときは、配列に push しただけになっていないかを確かめます。 ng2-charts は [data] に「新しいオブジェクト」が渡ったときに描き直す作りで、同じ配列の中身を変えただけでは描き直されませんでした(後述)。

ng2-charts 対応する Angular(peerDependencies) Chart.js
11.0.0(2026年9月) 22 以上 3.4 以上 または 4
10.x 21 以上 3.4 以上 または 4
9.x 20 以上 3.4 以上 または 4
8.x 19 以上 3.4 以上 または 4

確認環境:Angular 22.2.2・ng2-charts 11.0.0・Chart.js 4.5.1・TypeScript 6.0.3・Node.js 24.21.0 で ng build した本番ビルドを、Chromium 141(playwright-core 1.64.0)で表示しました。描画はスクリーンショットで、更新の結果は Chart.js が描いた棒の数(getDatasetMeta(0).data.length)で確かめました。表の対応は npm に公開されている各版の peerDependencies です(確認日 2026年10月13日)。

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Angular グラフ表示|ng2-chartsの使い方と更新されない原因」

手順1:インストールと provideCharts

ng add ng2-charts を使うと、インストールと app.config.ts の書き換えを一度に行います。 実行すると、app.config.ts に次の行が足されました。

import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
import { provideCharts, withDefaultRegisterables } from 'ng2-charts';

export const appConfig: ApplicationConfig = {
  providers: [provideBrowserGlobalErrorListeners(), provideRouter(routes), provideCharts(withDefaultRegisterables())],
};

npm で入れる場合は npm install ng2-charts chart.js のあと、上の provideCharts(...) を自分で書きます。ng2-charts 11 は @angular/cdk(22 以上)も peerDependencies に持っています。

withDefaultRegisterables() は、Chart.js の全種類のグラフ・目盛り・プラグインをまとめて登録します。使うグラフを絞って小さくする方法は後半で扱います。

手順2:棒・折れ線・円グラフのコンポーネント全文

3つとも、そのままコピーして使える形です。 グラフの外側の div に position: relative と高さを付けているのがポイントです(理由は後述)。

棒グラフ(sales-bar-chart.ts)

import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration } from 'chart.js';

@Component({
  selector: 'app-sales-bar-chart',
  imports: [BaseChartDirective],
  template: `
    <div class="chart-box">
      <canvas baseChart type="bar" [data]="data" [options]="options"></canvas>
    </div>
  `,
  styles: `.chart-box { position: relative; height: 320px; }`,
})
export class SalesBarChart {
  data: ChartConfiguration<'bar'>['data'] = {
    labels: ['4月', '5月', '6月', '7月', '8月', '9月'],
    datasets: [
      { label: '2025年度', data: [120, 135, 150, 142, 160, 171] },
      { label: '2026年度', data: [130, 148, 165, 170, 182, 195] },
    ],
  };

  options: ChartConfiguration<'bar'>['options'] = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: {
      legend: { position: 'bottom' },
      title: { display: true, text: '月別売上(百万円)' },
    },
    scales: { y: { beginAtZero: true } },
  };
}

折れ線グラフ(access-line-chart.ts)

import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration } from 'chart.js';

@Component({
  selector: 'app-access-line-chart',
  imports: [BaseChartDirective],
  template: `
    <div class="chart-box">
      <canvas baseChart type="line" [data]="data" [options]="options"></canvas>
    </div>
  `,
  styles: `.chart-box { position: relative; height: 320px; }`,
})
export class AccessLineChart {
  data: ChartConfiguration<'line'>['data'] = {
    labels: ['月', '火', '水', '木', '金', '土', '日'],
    datasets: [
      { label: 'PV', data: [3200, 2900, 3500, 3700, 3300, 2100, 1900], tension: 0.3, fill: true },
      { label: 'UU', data: [1800, 1700, 2000, 2100, 1900, 1200, 1100], tension: 0.3, borderDash: [6, 4] },
    ],
  };

  options: ChartConfiguration<'line'>['options'] = {
    responsive: true,
    maintainAspectRatio: false,
    interaction: { mode: 'index', intersect: false },
    plugins: { legend: { position: 'bottom' } },
  };
}

tension は線のなめらかさ(0 で直線)、fill: true は線の下を塗る設定、borderDash は点線です。interaction: { mode: 'index', intersect: false } にすると、同じ曜日の PV と UU が1つのツールチップに並びます。

円グラフ(share-pie-chart.ts)

import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration } from 'chart.js';

@Component({
  selector: 'app-share-pie-chart',
  imports: [BaseChartDirective],
  template: `
    <div class="chart-box">
      <canvas baseChart type="pie" [data]="data" [options]="options"></canvas>
    </div>
  `,
  styles: `.chart-box { position: relative; height: 320px; }`,
})
export class SharePieChart {
  data: ChartConfiguration<'pie'>['data'] = {
    labels: ['Java', 'TypeScript', 'Python', 'その他'],
    datasets: [{ data: [42, 28, 18, 12] }],
  };

  options: ChartConfiguration<'pie'>['options'] = {
    responsive: true,
    maintainAspectRatio: false,
    plugins: { legend: { position: 'right' } },
  };
}

ドーナツグラフにするなら type="doughnut" と ChartConfiguration<'doughnut'> に変えます。

3つを並べる(dashboard.ts)

import { Component } from '@angular/core';
import { SalesBarChart } from './sales-bar-chart';
import { AccessLineChart } from './access-line-chart';
import { SharePieChart } from './share-pie-chart';

@Component({
  selector: 'app-dashboard',
  imports: [SalesBarChart, AccessLineChart, SharePieChart],
  template: `
    <div class="grid">
      <app-sales-bar-chart />
      <app-access-line-chart />
      <app-share-pie-chart />
    </div>
  `,
  styles: `.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }`,
})
export class Dashboard {}

幅 1280px の画面で表示すると、3つの canvas はどれも幅約 410px・高さ 320px で描かれました。色は指定していませんが、棒・線・円のどれも自動で色分けされました。 withDefaultRegisterables() に Chart.js の Colors プラグインが含まれ、既定の色を順に当てるためです。凡例(legend)も position の指定どおり、棒と折れ線は下、円は右に出ました。

baseChart の入力・イベント一覧

ng2-charts 11.0.0 の型定義(BaseChartDirective)と README から抜き出した一覧です。

入力・出力 型 内容
type ChartType bar・line・pie・doughnut・radar・polarArea・bubble・scatter
data ChartData labels と datasets をまとめたもの
labels / datasets 配列 data の代わりに分けて渡す書き方
options ChartOptions Chart.js のオプションそのまま
legend boolean false で凡例を消す(指定しなければ Chart.js の既定で表示)
plugins Plugin[] そのグラフだけのプラグイン
(chartClick) / (chartHover) イベント クリック・ホバーした点(active)を受け取る

ディレクティブには update()・render()・hideDataset(index, hidden)・toBase64Image() のメソッドもあります。toBase64Image() はグラフを PNG の data URL にするので、画像として保存するときに使えます。

[legend] を書かなかったとき、凡例は表示されました(Chart.js の legend.options.display が true)。[legend]="false" を付けると false になり、凡例が消えました。

データを変えてもグラフが更新されない原因と4つの直し方

ボタンを押してデータを足す画面を作り、4つの書き方で、Chart.js が実際に描いた棒の数を記録しました。

import { Component, signal, viewChild } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';
import { ChartConfiguration, ChartData } from 'chart.js';

@Component({
  selector: 'app-live-chart',
  imports: [BaseChartDirective],
  template: `
    <button (click)="pushOnly()">① push だけ</button>
    <button (click)="pushAndUpdate()">② push + update()</button>
    <button (click)="replace()">③ 新しいオブジェクトに置き換え</button>
    <button (click)="addBySignal()">④ signal を update</button>
    <div class="chart-box"><canvas baseChart type="bar" [data]="data" [options]="options"></canvas></div>
    <div class="chart-box"><canvas baseChart type="bar" [data]="sigData()" [options]="options"></canvas></div>
  `,
  styles: `.chart-box { position: relative; height: 240px; }`,
})
export class LiveChart {
  chart = viewChild.required(BaseChartDirective); // 1つ目の canvas
  options: ChartConfiguration<'bar'>['options'] = { responsive: true, maintainAspectRatio: false, animation: false };

  data: ChartData<'bar'> = { labels: ['A', 'B'], datasets: [{ label: '件数', data: [3, 5] }] };

  /** ① 配列に push するだけ */
  pushOnly(): void {
    this.data.labels!.push('C');
    this.data.datasets[0].data.push(7);
  }

  /** ② push したあと update() を呼ぶ */
  pushAndUpdate(): void {
    this.data.labels!.push('D');
    this.data.datasets[0].data.push(4);
    this.chart().update();
  }

  /** ③ data を新しいオブジェクトにする */
  replace(): void {
    this.data = {
      labels: [...this.data.labels!, 'E'],
      datasets: [{ ...this.data.datasets[0], data: [...this.data.datasets[0].data, 6] }],
    };
  }

  /** ④ signal で持ち、update で新しいオブジェクトを作る */
  sigData = signal<ChartData<'bar'>>({ labels: ['A', 'B'], datasets: [{ label: '件数', data: [3, 5] }] });

  addBySignal(): void {
    this.sigData.update((d) => ({
      labels: [...d.labels!, `X${d.labels!.length}`],
      datasets: [{ ...d.datasets[0], data: [...d.datasets[0].data, 8] }],
    }));
  }
}
押したボタン data.labels の中身 描かれた棒の数 結果
最初 A,B 2 —
① push だけ A,B,C 2 描き直されない
② push + update() A,B,C,D 4 描き直された(①の C も出た)
③ 新しいオブジェクトに置き換え A,B,C,D,E 5 描き直された
④ signal を update(2回) A,B,X2,X3(2つ目のグラフ) 4 描き直された

①では、配列の中身は増えているのに、グラフは2本のままでした。 ng2-charts 11 のソースを見ると、ngOnChanges(入力が変わったときに呼ばれる処理)で data・options を Chart.js に渡して update() しています。Angular は「[data] に渡したオブジェクトが別のものになったか」で入力の変化を判断するため、同じ配列に push しただけでは ngOnChanges が呼ばれません。

直し方 書き方 向いている場面
② update() を呼ぶ viewChild(BaseChartDirective) で取り、update() 大きな配列を毎回作り直したくない、リアルタイム更新
③ 新しいオブジェクトにする スプレッド構文(...)で作り直して代入 普通の画面。書き忘れが起きにくい
④ signal で持つ signal.update() で新しいオブジェクトを返す signal で状態を持つ画面

なお、ソースでは type を変えたときだけ、グラフを一度破棄して作り直す(render())作りでした。棒グラフと折れ線を切り替えるボタンなら、[type] を変えるだけで作り直されます。signal の使い方は、関連記事「Angular Signals使い方|v22対応の全API早見表と実行結果つきコード」で扱っています。

グラフの高さが思いどおりにならないとき

Chart.js は親要素の大きさに合わせて canvas の大きさを決めます。 Chart.js のドキュメントには「親要素は position: relative で、その canvas 専用であること」とあります。

設定 動き(Chart.js のドキュメント)
maintainAspectRatio: true(既定) 幅に合わせ、縦横比を保って高さが決まる
aspectRatio の既定 円・ドーナツ・レーダー・鶏頭図は 1、それ以外は 2
maintainAspectRatio: false 親要素の高さに合わせる。親に高さを付ける

この記事のコードは maintainAspectRatio: false と、親の div の height: 320px の組み合わせで、canvas の高さが 320px になりました。

使うグラフだけ登録して小さくする

withDefaultRegisterables() の代わりに、使う部品だけを provideCharts({ registerables: [...] }) に並べられます。 棒グラフだけなら次のとおりです。

import { provideCharts } from 'ng2-charts';
import { BarController, BarElement, CategoryScale, LinearScale, Legend, Title, Tooltip, Colors } from 'chart.js';

provideCharts({
  registerables: [BarController, BarElement, CategoryScale, LinearScale, Legend, Title, Tooltip, Colors],
});

この記事の確認用のアプリ(ガード・テンプレートの確認用の画面も入ったもの)では、本番ビルドの main の大きさが次のように変わりました。

登録 main の大きさ 転送量の目安(圧縮後)
withDefaultRegisterables() 498.40 kB 137.63 kB
棒グラフに使う8つだけ 464.72 kB 128.12 kB

Chart.js のドキュメントにある、グラフの種類ごとに要る部品です。

グラフ コントローラー 要素 既定の目盛り
棒(bar) BarController BarElement CategoryScale・LinearScale
折れ線(line) LineController LineElement・PointElement CategoryScale・LinearScale
円(pie) PieController ArcElement なし
ドーナツ(doughnut) DoughnutController ArcElement なし
レーダー(radar) RadarController LineElement・PointElement RadialLinearScale

折れ線の fill: true には Filler、タイトルには Title、ツールチップには Tooltip、凡例には Legend のプラグインを足します。

登録が足りないときのエラー

状況 ブラウザのコンソールに出たエラー
provideCharts を書いていない(棒グラフを表示) ERROR Error: "linear" is not a registered scale.
棒グラフ用だけ登録して折れ線を表示 ERROR Error: "line" is not a registered controller.

is not a registered controller / scale が出たら、provideCharts の書き忘れか、そのグラフの部品の登録漏れです。

よくある質問

Q. グラフをクリックした項目を知りたいです。 A. (chartClick)="onClick($event)" で、クリックの情報と active(当たった点の配列)を受け取れます。ng2-charts 11 のソースでは、イベントを受け取る側があるときだけ Angular の処理に戻して通知する作りです。

Q. SSR(サーバー側の描画)でエラーになりませんか。 A. ng2-charts 11 のソースでは、ブラウザでないとき(isPlatformBrowser が false)は canvas の取得もグラフの作成も行わない作りになっています。グラフはブラウザで表示されたときに描かれます。

Q. ダークモードで文字の色を変えたいです。 A. ng2-charts の ThemeService の setColorschemesOptions() に、上書きしたいオプションを渡すと、表示中のグラフにまとめて反映されます(README の Dynamic Theming)。

Q. Angular Material と一緒に使えますか。 A. ng2-charts 11 は @angular/cdk を peerDependencies に持っています。Angular Material の導入は、関連記事「Angular Materialの使い方|導入からテーブル・ダイアログまで」で扱っています。

まとめ

  • provideCharts(withDefaultRegisterables()) を app.config に書き、BaseChartDirective を imports に入れて <canvas baseChart>
  • ng2-charts 11 は Angular 22 以上、10 は 21、9 は 20 に対応
  • 配列に push しただけではグラフは変わらなかった。update()・新しいオブジェクトの代入・signal のどれかで更新する
  • 高さは 親を position: relative にして高さを付け、maintainAspectRatio: false
  • is not a registered controller は部品の登録漏れ。使う部品だけ登録すると main が約 34 kB 小さくなった

参考・出典

確認日はいずれも 2026年10月13日です。

  • ng2-charts(GitHub・README):https://github.com/valor-software/ng2-charts
  • ng2-charts(npm):https://www.npmjs.com/package/ng2-charts
  • Chart.js「Integration」(Bundlers・tree-shaking):https://www.chartjs.org/docs/latest/getting-started/integration.html
  • Chart.js「Responsive Charts」:https://www.chartjs.org/docs/latest/configuration/responsive.html
  • Chart.js「Updating Charts」:https://www.chartjs.org/docs/latest/developers/updates.html

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Angular グラフ表示|ng2-chartsの使い方と更新されない原因」

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?