← Back to all snippets
JAVASCRIPT

Integrating Chart.js into a Vue 3 Component

Learn to wrap a third-party JavaScript library like Chart.js within a Vue 3 component, managing its lifecycle and data reactivity for dynamic visualizations.

// ChartComponent.vue
<template>
  <div>
    <canvas ref="chartCanvas"></canvas>
  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import Chart from 'chart.js/auto'; // Or specific modules like 'chart.js/auto'

const props = defineProps({
  chartData: {
    type: Object,
    required: true,
    default: () => ({
      labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
      datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
          'rgba(255, 206, 86, 0.2)',
          'rgba(75, 192, 192, 0.2)',
          'rgba(153, 102, 255, 0.2)',
          'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
          'rgba(255, 99, 132, 1)',
          'rgba(54, 162, 235, 1)',
          'rgba(255, 206, 86, 1)',
          'rgba(75, 192, 192, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
      }]
    })
  },
  chartOptions: {
    type: Object,
    default: () => ({
      responsive: true,
      maintainAspectRatio: false
    })
  },
  chartType: {
    type: String,
    default: 'bar' // bar, line, pie, etc.
  }
});

const chartCanvas = ref(null);
let myChart = null;

const createChart = () => {
  if (myChart) {
    myChart.destroy(); // Destroy existing chart before creating a new one
  }
  myChart = new Chart(chartCanvas.value, {
    type: props.chartType,
    data: props.chartData,
    options: props.chartOptions
  });
};

onMounted(() => {
  createChart();
});

onBeforeUnmount(() => {
  if (myChart) {
    myChart.destroy();
    myChart = null;
  }
});

// Watch for changes in chartData or chartType to re-render the chart
watch(() => [props.chartData, props.chartType, props.chartOptions], () => {
  createChart();
}, { deep: true }); // Deep watch for chartData object changes
</script>

<style scoped>
canvas {
  max-width: 600px; /* Example styling */
  max-height: 400px;
}
</style>

<!-- Example usage in ParentComponent.vue -->
<template>
  <div>
    <ChartComponent :chartData="data" :chartType="chartType" />
    <button @click="updateChartData">Update Data</button>
    <button @click="toggleChartType">Toggle Type</button>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import ChartComponent from './ChartComponent.vue';

const data = ref({
  labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  datasets: [{
    label: 'Sales',
    data: [100, 150, 200, 120, 180, 250, 190],
    backgroundColor: 'rgba(75, 192, 192, 0.6)'
  }]
});

const chartType = ref('bar');

const updateChartData = () => {
  data.value = {
    ...data.value,
    datasets: [{
      ...data.value.datasets[0],
      data: data.value.datasets[0].data.map(d => d + Math.floor(Math.random() * 50) - 25)
    }]
  };
};

const toggleChartType = () => {
  chartType.value = chartType.value === 'bar' ? 'line' : 'bar';
};
</script>
How it works: This snippet illustrates how to integrate a third-party JavaScript library like Chart.js into a Vue 3 component. It uses a `ref` to link to the canvas element, `onMounted` to initialize the chart once the component is in the DOM, and `onBeforeUnmount` to destroy the chart instance to prevent memory leaks. A `watch` listener intelligently recreates the chart whenever `chartData`, `chartType`, or `chartOptions` props change, ensuring the visualization stays reactive and up-to-date with your application's state.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs