Search code examples
chartsnuxt.jsnuxt3.jsvue-chartjs

What is the proper way to include chart.js with Nuxt 3.4?


There are some tutorials out there (e.g. https://medium.com/geekculture/chart-js-in-nuxt-js-how-to-implement-c255a2657b02) that show how to integrate Chart.js with an earlier version of Nuxt 3 or even Nuxt 2. But they do not work for various reasons. This tutorial e.g. https://dev.to/anggakswr/chart-js-in-nuxt-js-4hjf causes a 500 error:

Cannot read properties of undefined (reading 'component')

at ./plugins/charts.js:6:31
at async ViteNodeRunner.directRequest (./node_modules/vite- 
node/dist/client.mjs:331:5)

Also, there are different approaches: one tutorial/example uses the "Nuxt plugin" way, another the "Nuxt component" way...

I tried the plugin-way based on the docu here: https://nuxt.com/docs/guide/directory-structure/plugins#vue-plugins:

// plugins/charts.js

import { Bar } from "vue-chartjs"

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.vueApp.use(Bar)
})

But as soon as I run npm run dev, I get this warning:

[Vue warn]: A plugin must either be a function or an object with an "install" function.

And later:

[Vue warn]: Failed to resolve component: BarChart
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. 
at <Chart onVnodeUnmounted=fn<onVnodeUnmounted> ref=Ref< undefined > > 

Here is a codesandbox: https://codesandbox.io/p/sandbox/gracious-lumiere-88bw4j

What do I have to do to get (vue-)chart.js working?


Solution

  • Install chart.js

    npm i vue-chartjs chart.js
    

    There are two possible options you can implement it.

    1. Globally register ChartJS

    ~/plugins/chartjs.ts

    import { Chart, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    export default defineNuxtPlugin(() => {
        Chart.register(CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend)
    })

    Component usage example.

    <script lang="ts" setup>
    import { Bar } from 'vue-chartjs'
    const chartData = ref({
      labels: ['January', 'February', 'March', 'April', 'May'],
      datasets: [
        {
          label: 'Data One',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 50, 10],
        },
      ],
    })
    const chartOptions = ref({
      responsive: true,
      maintainAspectRatio: false,
    })
    </script>
    <template>
      <div>
        <Bar
          :data="chartData"
          :options="chartOptions"
        />
      </div>
    </template>

    Expected Result enter image description here

    2. Manually register ChatJS

    <script lang="ts" setup>
    import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    import { Bar } from 'vue-chartjs'
    
    // Register
    ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
    
    
    const chartData = ref({
      labels: ['January', 'February', 'March', 'April', 'May'],
      datasets: [
        {
          label: 'Data One',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 50, 10],
        },
      ],
    })
    const chartOptions = ref({
      responsive: true,
      maintainAspectRatio: false,
    })
    
    </script>
    <template>
      <div>
        <Bar
          :data="chartData"
          :options="chartOptions"
        />
      </div>
    </template>
    <style scoped lang="css"></style>

    Expected Result enter image description here

    Both will work depending on your needs.

    Note: Due to tree-shaking, you will need to replace BarElement in the above imports with the relevant Element(s) if you require a different chart type.