--- name: chartjs-integrations description: This skill should be used when the user asks "Chart.js React", "react-chartjs-2", "Chart.js Vue", "vue-chartjs", "Chart.js Angular", "ng2-charts", "Chart.js Rails", "Chart.js Rails 8", "Chart.js importmaps", "Chart.js Stimulus", "Chart.js Turbo", "Chart.js Hotwire", "Chart.js SSR", "Chart.js Next.js", "Chart.js Nuxt", or needs help integrating Chart.js v4.5.1 with frontend frameworks. --- # Chart.js Framework Integrations (v4.5.1) Complete guide to integrating Chart.js with React, Vue, Angular, Rails 8, and other frameworks. ## React Integration (react-chartjs-2) ### Installation ```bash npm install react-chartjs-2 chart.js ``` ### Basic Usage ```jsx import { Bar } from 'react-chartjs-2'; import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js'; // Register components ChartJS.register( CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend ); function BarChart() { const data = { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], datasets: [{ label: 'Sales', data: [12, 19, 3, 5, 2], backgroundColor: 'rgba(54, 162, 235, 0.5)' }] }; const options = { responsive: true, plugins: { legend: { position: 'top' }, title: { display: true, text: 'Monthly Sales' } } }; return ; } ``` ### Available Components ```jsx import { Bar, Line, Pie, Doughnut, Radar, PolarArea, Bubble, Scatter } from 'react-chartjs-2'; ``` ### Chart Reference ```jsx import { useRef } from 'react'; import { Bar, getElementAtEvent } from 'react-chartjs-2'; function InteractiveChart() { const chartRef = useRef(); const handleClick = (event) => { const element = getElementAtEvent(chartRef.current, event); if (element.length > 0) { const { datasetIndex, index } = element[0]; console.log('Clicked:', datasetIndex, index); } }; return ( ); } ``` ### Dynamic Updates ```jsx import { useState, useEffect } from 'react'; import { Line } from 'react-chartjs-2'; function LiveChart() { const [chartData, setChartData] = useState({ labels: [], datasets: [{ label: 'Live Data', data: [], borderColor: 'rgb(75, 192, 192)' }] }); useEffect(() => { const interval = setInterval(() => { setChartData(prev => ({ ...prev, labels: [...prev.labels, new Date().toLocaleTimeString()].slice(-10), datasets: [{ ...prev.datasets[0], data: [...prev.datasets[0].data, Math.random() * 100].slice(-10) }] })); }, 1000); return () => clearInterval(interval); }, []); return ; } ``` ## Vue Integration (vue-chartjs) ### Installation ```bash npm install vue-chartjs chart.js ``` ### Vue 3 Composition API ```vue ``` ### Vue 3 Options API ```vue ``` ### Reactive Updates in Vue ```vue ``` ## Angular Integration (ng2-charts) ### Installation ```bash npm install ng2-charts chart.js ``` ### Module Setup ```typescript // app.module.ts import { NgModule } from '@angular/core'; import { NgChartsModule } from 'ng2-charts'; @NgModule({ imports: [NgChartsModule] }) export class AppModule {} ``` ### Component Usage ```typescript // chart.component.ts import { Component } from '@angular/core'; import { ChartConfiguration, ChartType } from 'chart.js'; @Component({ selector: 'app-chart', template: ` ` }) export class ChartComponent { barChartType: ChartType = 'bar'; barChartData: ChartConfiguration<'bar'>['data'] = { labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], datasets: [{ label: 'Sales', data: [12, 19, 3, 5, 2], backgroundColor: 'rgba(54, 162, 235, 0.5)' }] }; barChartOptions: ChartConfiguration<'bar'>['options'] = { responsive: true, plugins: { legend: { position: 'top' } } }; } ``` ### Standalone Component (Angular 17+) ```typescript import { Component } from '@angular/core'; import { BaseChartDirective } from 'ng2-charts'; @Component({ selector: 'app-chart', standalone: true, imports: [BaseChartDirective], template: ` ` }) export class ChartComponent { // ... } ``` ## Rails 8 Integration Rails 8 offers multiple approaches for Chart.js integration. ### Option 1: Importmaps (Recommended) ```bash # Pin Chart.js bin/importmap pin chart.js ``` ```javascript // app/javascript/controllers/chart_controller.js import { Controller } from "@hotwired/stimulus"; import Chart from "chart.js/auto"; export default class extends Controller { static targets = ["canvas"]; static values = { type: { type: String, default: "bar" }, data: Object, options: { type: Object, default: {} } }; connect() { this.chart = new Chart(this.canvasTarget, { type: this.typeValue, data: this.dataValue, options: this.optionsValue }); } disconnect() { if (this.chart) { this.chart.destroy(); } } // Handle Turbo frame updates dataValueChanged() { if (this.chart) { this.chart.data = this.dataValue; this.chart.update(); } } } ``` ```erb
``` ```ruby # app/controllers/charts_controller.rb class ChartsController < ApplicationController def show @chart_data = { labels: %w[Jan Feb Mar Apr May], datasets: [{ label: 'Sales', data: [12, 19, 3, 5, 2], backgroundColor: 'rgba(54, 162, 235, 0.5)' }] } @chart_options = { responsive: true, plugins: { legend: { position: 'top' } } } end end ``` ### Option 2: esbuild/jsbundling-rails ```bash # Gemfile gem 'jsbundling-rails' # Install rails javascript:install:esbuild npm install chart.js ``` ```javascript // app/javascript/application.js import Chart from 'chart.js/auto'; window.Chart = Chart; ``` ### Option 3: Propshaft + CDN ```erb ``` ### Turbo Compatibility Handle Turbo Drive page visits: ```javascript // app/javascript/controllers/chart_controller.js import { Controller } from "@hotwired/stimulus"; import Chart from "chart.js/auto"; export default class extends Controller { static targets = ["canvas"]; static values = { config: Object }; connect() { this.createChart(); } disconnect() { this.destroyChart(); } createChart() { const ctx = this.canvasTarget.getContext('2d'); this.chart = new Chart(ctx, this.configValue); } destroyChart() { if (this.chart) { this.chart.destroy(); this.chart = null; } } // Re-render on Turbo cache restore reconnect() { this.destroyChart(); this.createChart(); } } ``` ### Turbo Streams Updates ```ruby # Update chart via Turbo Stream turbo_stream.replace "sales-chart" do render partial: "charts/sales", locals: { data: @new_data } end ``` ```erb
``` ### Rails Helper ```ruby # app/helpers/chart_helper.rb module ChartHelper def chart_tag(type:, data:, options: {}, **html_options) config = { type: type, data: data, options: options } content_tag :div, data: { controller: 'chart', chart_config_value: config.to_json }, **html_options do content_tag :canvas, '', data: { chart_target: 'canvas' } end end end ``` ```erb <%= chart_tag type: 'bar', data: @chart_data, options: @chart_options %> ``` ## Vanilla JavaScript Patterns ### Module Pattern ```javascript // chart-manager.js export class ChartManager { constructor(canvasId, config) { this.canvas = document.getElementById(canvasId); this.chart = new Chart(this.canvas, config); } updateData(newData) { this.chart.data = newData; this.chart.update(); } destroy() { this.chart.destroy(); } } ``` ### Web Component ```javascript class ChartComponent extends HTMLElement { connectedCallback() { const canvas = document.createElement('canvas'); this.appendChild(canvas); const config = JSON.parse(this.getAttribute('config')); this.chart = new Chart(canvas, config); } disconnectedCallback() { if (this.chart) { this.chart.destroy(); } } } customElements.define('chart-component', ChartComponent); ``` ```html ``` ## Server-Side Rendering (SSR) Chart.js requires a canvas element. For SSR: ### Next.js ```jsx 'use client'; // Mark as client component import dynamic from 'next/dynamic'; const Chart = dynamic( () => import('react-chartjs-2').then(mod => mod.Bar), { ssr: false } ); export default function Page() { return ; } ``` ### Nuxt 3 ```vue ``` ## Date Adapters For time-based axes, install a date adapter: ```bash # date-fns (recommended) npm install chartjs-adapter-date-fns date-fns # Moment.js npm install chartjs-adapter-moment moment # Luxon npm install chartjs-adapter-luxon luxon # Day.js npm install chartjs-adapter-dayjs-4 dayjs ``` ```javascript // Import after Chart.js import 'chartjs-adapter-date-fns'; ``` ## Additional Resources - See `examples/rails-stimulus.md` for complete Rails 8 examples with Turbo integration