vue-chartjs

repository·main·Indexed 26 days ago

https://github.com/apertureless/vue-chartjs

A Vue.js wrapper for Chart.js (supporting v4) that allows developers to create reusable chart components. It provides pre-typed components for common chart types such as Bar, Line, Pie, Doughnut, PolarArea, Radar, Bubble, and Scatter, along with a `createTypedChart` factory for custom chart types. The library includes utility functions for event handling, TypeScript support via ChartProps and ChartComponentRef, and built-in accessibility props.

Tokens
6.5K
Snippets
19
Records
37
Agent score
87%

What's inside vue-chartjs

  1. Update charts reactively

    main

    vue-chartjs automatically watches for changes in the :data and :options props. If you pass new data or options, the wrapper will update or re-render the chart.

    Handling Read-only Data: If you encounter Vue's Target is readonly warning when updating chartData (common when using read-only reactive values), you can bypass this by passing a clone of the data:

    <template>
      <Bar :data="JSON.stringify(JSON.parse(chartData))" :options="chartOptions" />
    </template>

    Note: Using structuredClone on a read-only computed value will result in a Write operation failed: computed value is readonly error. For best results, use a writable computed value.

  2. Render charts with asynchronous API data

    main

    When fetching data from an API, Chart.js may attempt to render before the data arrives because it expects synchronous data access. To prevent errors, use a v-if directive to ensure the chart component only mounts once the data has been successfully loaded.

    <template>
      <div class="container">
        <Bar v-if="loaded" :data="chartData" />
      </div>
    </template>
    
    <script>
    import { Bar } from 'vue-chartjs'
    import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    
    ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
    
    export default {
      name: 'BarChart',
      components: { Bar },
      data: () => ({
        loaded: false,
        chartData: null
      }),
      async mounted () {
        this.loaded = false
    
        try {
          const { userlist } = await fetch('/api/userlist')
          this.chartdata = userlist
    
          this.loaded = true
        } catch (e) {
          console.error(e)
        }
      }
    }
    </script>
  3. Install vue-chartjs and chart.js

    main

    To use vue-chartjs, you must also install chart.js as a dependency because it is a peerDependency. This allows you to control the version of chart.js used in your project. vue-chartjs supports Chart.js v4.

    Install using your preferred package manager:

    pnpm add vue-chartjs chart.js
    # or
    yarn add vue-chartjs chart.js
    # or
    npm i vue-chartjs chart.js
  4. Apply dynamic styles to chart containers

    main

    To change the height and width of a chart container dynamically, set responsive: true in your chart options and apply styles to the component via the :style prop.

    Important: You must set position: relative in your styles for the chart to render correctly within the container.

    <template>
      <div>
        <Bar :style="myStyles"/>
      </div>
    </template>
    
    <script>
    import { Bar } from 'vue-chartjs'
    import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    
    ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
    
    export default {
      name: 'BarChart',
      components: { Bar },
      computed: {
        myStyles () {
          return {
            height: `${/* mutable height */}px`,
            position: 'relative'
          }
        }
      }
    }
    </script>
  5. Create reusable charts using Vue props

    main

    To create reusable chart components, use Vue.js props to pass in data and options. This separates the presentation logic from the data fetching logic, allowing the parent component to manage data retrieval while the chart component remains focused on rendering.

    <template>
      <Bar :data="chartData" :options="chartOptions" />
    </template>
    
    <script>
    import { Bar } from 'vue-chartjs'
    import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    
    ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
    
    export default {
      name: 'BarChart',
      components: { Bar },
      props: {
        chartData: {
            type: Object,
            required: true
          },
        chartOptions: {
          type: Object,
          default: () => {}
        }
      }
    }
    </script>
  6. Configure accessibility for charts

    main

    To improve accessibility, you can use the following methods:

    1. aria-label: Pass a descriptive string directly via the aria-label prop.
    2. aria-describedby: Reference an external element (like a data table) using the aria-describedby prop.
    3. Fallback Content: Provide fallback text for browsers that cannot render the canvas element by using the component's default slot.
    <!-- aria-label example -->
    <BarChart aria-label="Sales figures for 2022 to 2024." />
    
    <!-- aria-describedby example -->
    <BarChart aria-describedby="my-data-table" />
    <table id="my-data-table">...</table>
    
    <!-- Fallback content example -->
    <BarChart>Chart couldn't be loaded.</BarChart>
  7. Enable tree-shaking in vue-chartjs v4

    main

    In v4, the library is tree-shakable. To reduce bundle size, you should manually import and register the specific controllers, elements, scales, and plugins you need from chart.js using ChartJS.register().

    Note that typed chart components (like Pie) register their controllers automatically, so you do not need to register them explicitly. However, you still need to register elements, scales, and plugins.

    import { Bar } from 'vue-chartjs'
    import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
    
    ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
  8. Migrate to ESM for vue-chartjs v5.0

    main

    Starting with vue-chartjs v5.0, both the library and its dependency Chart.js v4 are ESM-only packages. To use them, your project must be configured as an ESM module by adding "type": "module" to your package.json.

    If you use Jest, you must follow the official Jest documentation to enable ESM support. Alternatively, it is recommended to migrate to Vitest, which supports ESM out of the box.

    // package.json
    {
      "type": "module"
    }