Get the FREE Ultimate OpenClaw Setup Guide →

chartjs-integrations

npx machina-cli add skill sjnims/chartjs-expert/chartjs-integrations --openclaw
Files (1)
SKILL.md
11.9 KB

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

npm install react-chartjs-2 chart.js

Basic Usage

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 <Bar data={data} options={options} />;
}

Available Components

import {
  Bar,
  Line,
  Pie,
  Doughnut,
  Radar,
  PolarArea,
  Bubble,
  Scatter
} from 'react-chartjs-2';

Chart Reference

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 (
    <Bar
      ref={chartRef}
      data={data}
      onClick={handleClick}
    />
  );
}

Dynamic Updates

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 <Line data={chartData} />;
}

Vue Integration (vue-chartjs)

Installation

npm install vue-chartjs chart.js

Vue 3 Composition API

<template>
  <Bar :data="chartData" :options="chartOptions" />
</template>

<script setup>
import { Bar } from 'vue-chartjs';
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from 'chart.js';

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

const chartData = {
  labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
  datasets: [{
    label: 'Sales',
    data: [12, 19, 3, 5, 2],
    backgroundColor: 'rgba(54, 162, 235, 0.5)'
  }]
};

const chartOptions = {
  responsive: true,
  plugins: {
    legend: { position: 'top' }
  }
};
</script>

Vue 3 Options API

<template>
  <Bar :data="chartData" :options="chartOptions" />
</template>

<script>
import { Bar } from 'vue-chartjs';
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from 'chart.js';

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

export default {
  components: { Bar },
  data() {
    return {
      chartData: {
        labels: ['Jan', 'Feb', 'Mar'],
        datasets: [{ label: 'Sales', data: [10, 20, 30] }]
      },
      chartOptions: {
        responsive: true
      }
    };
  }
};
</script>

Reactive Updates in Vue

<template>
  <Line :data="chartData" :options="chartOptions" />
</template>

<script setup>
import { ref, watch } from 'vue';
import { Line } from 'vue-chartjs';

const chartData = ref({
  labels: ['Jan', 'Feb', 'Mar'],
  datasets: [{
    label: 'Data',
    data: [10, 20, 30]
  }]
});

// Chart will automatically update when chartData changes
function updateData(newData) {
  chartData.value = {
    ...chartData.value,
    datasets: [{
      ...chartData.value.datasets[0],
      data: newData
    }]
  };
}
</script>

Angular Integration (ng2-charts)

Installation

npm install ng2-charts chart.js

Module Setup

// app.module.ts
import { NgModule } from '@angular/core';
import { NgChartsModule } from 'ng2-charts';

@NgModule({
  imports: [NgChartsModule]
})
export class AppModule {}

Component Usage

// chart.component.ts
import { Component } from '@angular/core';
import { ChartConfiguration, ChartType } from 'chart.js';

@Component({
  selector: 'app-chart',
  template: `
    <canvas baseChart
      [data]="barChartData"
      [options]="barChartOptions"
      [type]="barChartType">
    </canvas>
  `
})
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+)

import { Component } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts';

@Component({
  selector: 'app-chart',
  standalone: true,
  imports: [BaseChartDirective],
  template: `
    <canvas baseChart
      [data]="chartData"
      [options]="chartOptions"
      type="bar">
    </canvas>
  `
})
export class ChartComponent {
  // ...
}

Rails 8 Integration

Rails 8 offers multiple approaches for Chart.js integration.

Option 1: Importmaps (Recommended)

# Pin Chart.js
bin/importmap pin chart.js
// 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();
    }
  }
}
<!-- app/views/charts/show.html.erb -->
<div data-controller="chart"
     data-chart-type-value="bar"
     data-chart-data-value="<%= @chart_data.to_json %>"
     data-chart-options-value="<%= @chart_options.to_json %>">
  <canvas data-chart-target="canvas"></canvas>
</div>
# 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

# Gemfile
gem 'jsbundling-rails'

# Install
rails javascript:install:esbuild
npm install chart.js
// app/javascript/application.js
import Chart from 'chart.js/auto';
window.Chart = Chart;

Option 3: Propshaft + CDN

<!-- app/views/layouts/application.html.erb -->
<head>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>

Turbo Compatibility

Handle Turbo Drive page visits:

// 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

# Update chart via Turbo Stream
turbo_stream.replace "sales-chart" do
  render partial: "charts/sales", locals: { data: @new_data }
end
<!-- app/views/charts/_sales.html.erb -->
<div id="sales-chart"
     data-controller="chart"
     data-chart-config-value="<%= config.to_json %>">
  <canvas data-chart-target="canvas"></canvas>
</div>

Rails Helper

# 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
<%= chart_tag type: 'bar', data: @chart_data, options: @chart_options %>

Vanilla JavaScript Patterns

Module Pattern

// 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

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);
<chart-component config='{"type":"bar","data":{"labels":["A","B"],"datasets":[{"data":[1,2]}]}}'></chart-component>

Server-Side Rendering (SSR)

Chart.js requires a canvas element. For SSR:

Next.js

'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 <Chart data={data} options={options} />;
}

Nuxt 3

<template>
  <ClientOnly>
    <Bar :data="chartData" :options="chartOptions" />
  </ClientOnly>
</template>

<script setup>
import { Bar } from 'vue-chartjs';
// Register Chart.js components...
</script>

Date Adapters

For time-based axes, install a date adapter:

# 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
// Import after Chart.js
import 'chartjs-adapter-date-fns';

Additional Resources

  • See examples/rails-stimulus.md for complete Rails 8 examples with Turbo integration

Source

git clone https://github.com/sjnims/chartjs-expert/blob/main/skills/chartjs-integrations/SKILL.mdView on GitHub

Overview

Chart.js Framework Integrations guide shows how to wire Chart.js v4.5.1 into React, Vue, Angular, Rails 8, and beyond. It covers installation, component registration, data structures, and common patterns for live updates and SSR-friendly setups.

How This Skill Works

Each framework section demonstrates installing dependencies, registering Chart.js components (e.g., CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend), and creating a chart-ready data object with labels and datasets. The examples then render the chart component (Bar, Line, etc.) with the prepared data and options.

When to Use It

  • You’re building a React app and want to use react-chartjs-2.
  • You’re integrating Chart.js into Vue 3 with vue-chartjs.
  • You’re adding Chart.js to an Angular project using ng2-charts.
  • You’re working with Rails 8 and need Chart.js examples.
  • You’re setting up SSR or Next.js / Nuxt projects with Chart.js.

Quick Start

  1. Step 1: Install framework-specific packages (e.g., react-chartjs-2 and chart.js for React, vue-chartjs for Vue).
  2. Step 2: Import and register Chart.js components (CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend).
  3. Step 3: Create a data object with labels and datasets, then render the chart component with data and options.

Best Practices

  • Register only the required Chart.js components for your chart (e.g., CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend).
  • Keep data and options in a single source of truth and pass them as props to the chart component.
  • Make the chart responsive (responsive: true) and manage container size for correct rendering.
  • For live data, update state with minimal re-renders and clean up intervals or subscriptions.
  • When SSR is involved, consider dynamic imports or lazy loading to avoid browser-only code issues.

Example Use Cases

  • A React dashboard using react-chartjs-2 to display monthly sales.
  • A Vue 3 admin panel showing user growth with Bar and Line charts.
  • An Angular app with charts integrated into a component-driven UI.
  • A Rails 8 page rendering analytics charts with Chart.js.
  • A Next.js app employing SSR-friendly Chart.js visuals with dynamic imports.

Frequently Asked Questions

Add this skill to your agents
Sponsor this space

Reach thousands of developers