# Examples

# Chart with props

template
import { defineComponent } from 'vue'
import { Pie } from 'vue3-chart-v2'

export default defineComponent({
  name: 'MonthlyChart',
  extends: Pie,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    },
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})

After that you can add your chart component to a parent component

<template>
  <MonthlyChart v-bind:chartData="state.chartData" v-bind:chartOptions="state.chartOptions" />
</template>

<script>
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'App',
  data () {
    return {
      state: {
        chartData: {
          datasets: [
            {
              data: [1, 2, 3, 4],
              backgroundColor: ['Red', 'Yellow', 'Blue', 'Green']
            }
          ],
          // These labels appear in the legend and in the tooltips when hovering different arcs
          labels: ['Red', 'Yellow', 'Blue', 'Green']
        },
        chartOptions: {
          responsive: false
        }
      }
    }
  }
})
</script>

Output

jsx
import { defineComponent } from 'vue'
import { Bar } from 'vue3-chart-v2'

export default defineComponent({
  name: 'MonthlyChart',
  extends: Bar,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    },
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})

After that you can add your chart component to a parent component

export default defineComponent({
  data () {
    return {
      state: {
        chartData: {
          datasets: [
            {
              data: [1, 2, 3, 4],
              backgroundColor: ['Red', 'Yellow', 'Blue', 'Green']
            }
          ],
          // These labels appear in the legend and in the tooltips when hovering different arcs
          labels: ['Red', 'Yellow', 'Blue', 'Green']
        },
        chartOptions: {
          responsive: false
        }
      }
    }
  },
  render () {
    return (
      <Fragment>
        <MonthlyChart chartData={this.state.chartData} chartOptions={this.state.chartOptions} />
      </Fragment>
    )
  }
})

Output

# Chart with local data

template

SportChart.vue

<script>
import { defineComponent } from 'vue'
import { Radar } from 'vue3-chart-v2'

export default defineComponent({
  name: 'SportChart',
  extends: Radar,
  data () {
    return {
      state: {
        chartData: {
           labels: ['Running', 'Swimming', 'Eating', 'Cycling'],
            datasets: [
              {
                label: 'Human 1',
                data: [20, 10, 4, 2]
              },
              {
                label: 'Human 2',
                data: [10, 20, 2, 4]
              }
            ]
        },
        chartOptions: {
          responsive: false
        }
      }
    }
  },
  mounted () {
    this.renderChart(this.state.chartData, this.state.chartOptions)
  }
})
</script>

After that you can render your chart component anywhere

<template>
  <SportChart />
</template>

<script>
import { defineComponent } from 'vue'
import SportChart from './path/to/SportChart'

export default defineComponent({
  name: 'App',
  components: {
    SportChart
  }
})
</script>

Output

jsx

SportChart.js

import { defineComponent } from 'vue'
import { Radar } from 'vue3-chart-v2'

export default defineComponent({
  name: 'SportChart',
  extends: Radar,
  data () {
    return {
      state: {
        chartData: {
           labels: ['Running', 'Swimming', 'Eating', 'Cycling'],
            datasets: [
              {
                label: 'Human 1',
                data: [20, 10, 4, 2]
              },
              {
                label: 'Human 2',
                data: [10, 20, 2, 4]
              }
            ]
        },
        chartOptions: {
          responsive: false
        }
      }
    }
  },
  mounted () {
    this.renderChart(this.state.chartData, this.state.chartOptions)
  }
})

After that you can render your chart component anywhere

import { defineComponent, Fragment } from 'vue'
import SportChart from './path/to/SportChart'

export default defineComponent({
  name: 'App',
  render () {
    return (
      <Fragment>
        <SportChart />
      </Fragment>
    )
  }
})

Output

# Chart with API data

template

A common pattern is to use an API to retrieve your data. However, there are some things to keep in mind. The most common problem is that you mount your chart component directly and pass in data from an asyncronous API call. The problem with this approach is that Chart.js tries to render your chart and access the chart data syncronously, so your chart mounts before the API data arrives.

To prevent this, a simple v-if is the best solution.

Create your chart component with a data prop and options prop, so we can pass in our data and options from a container component.

import { defineComponent } from 'vue'
import { Line } from 'vue3-chart-v2'

export default defineComponent({
  extends: Line,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    },
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})
</script>

Then create a container component, which handles your api call or vuex connection.



 



































<template>
  <MonthlyChart 
    v-if="state.isLoaded" 
    v-bind:chartData="state.chartData" 
    v-bind:chartOptions="state.chartOptions" 
  />
</template>

<script>
import { defineComponent } from 'vue'
import LineChart from './LineChart.vue' // Or LineChart.js

export default defineComponent({
  name: 'MonthlyChartContainer',
  extends: Bar,
  data () {
    return {
      state: {
        isLoaded: false,
        chartData: null
      }
    }
  },
  mounted () {
    this.state.isLoaded = false
    fetch('/api/userlist')
    .then((response) => response.json())
    .then((result) => {
      this.state.chartData = result
      this.state.isLoaded = false
    })
    .cath((err) => {
      console.error(err)
    })
  }
})
</script>
jsx

A common pattern is to use an API to retrieve your data. However, there are some things to keep in mind. The most common problem is that you mount your chart component directly and pass in data from an asyncronous API call. The problem with this approach is that Chart.js tries to render your chart and access the chart data syncronously, so your chart mounts before the API data arrives.

To prevent this, a simple && or if is the best solution.

Create your chart component with a data prop and options prop, so we can pass in our data and options from a container component.

import { defineComponent } from 'vue'
import { Line } from 'vue3-chart-v2'

export default defineComponent({
  extends: Line,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    },
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})































 







import { defineComponent } from 'vue'
import LineChart from './LineChart.vue' // Or LineChart.js

export default defineComponent({
  name: 'MonthlyChartContainer',
  extends: Bar,
  data () {
    return {
      state: {
        isLoaded: false,
        chartData: null
      }
    }
  },
  mounted () {
    this.state.isLoaded = false
    fetch('/api/userlist')
    .then((response) => response.json())
    .then((result) => {
      this.state.chartData = result
      this.state.isLoaded = false
    })
    .cath((err) => {
      console.error(err)
    })
  },
  render () {
    return (
      <Fragment>
      {
        this.state.isLoaded && (
          <MonthlyChart chartData={this.state.chartData} chartOptions={this.state.chartOptions} />
        )
      }
      </Fragment>
    )
  }
})

# Chart with dynamic data

template

// LineChart.js

import { defineComponent } from 'vue'
import { Line } from 'vue3-chart-v2'

export default defineComponent({
  extends: Line,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    }
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})

// import your LineChart.js

<template>
  <LineChart v-bind:chartData="state.chartData" />
  <button v-on:click="fillData">Randomize</button>
</template>

<script>
import { defineComponent } from 'vue'
import LineChart from './path/to/LineChart.js'

export default defineComponent({
  name: 'App',
  data () {
    return {
      state: {
        chartData: {},
        chartOptions: {
          responsive: true
        }
      }
    }
  },
  beforeMount () {
    this.fillData()
  },
  methods: {
    fillData () {
      this.state.chartData = {
        labels: ['Label 1', 'Label 2'],
        datasets: [
          {
            label: 'Data One',
            backgroundColor: '#f87979',
            data: [this.getRandomInt(), this.getRandomInt()]
          }
        ]
      }
    },
    getRandomInt () {
      return Math.floor(Math.random() * (10 - 5 + 1)) + 10
    }
  },
})
</script>

Output

jsx

// LineChart.js

import { defineComponent } from 'vue'
import { Line } from 'vue3-chart-v2'

export default defineComponent({
  extends: Line,
  props: {
    chartData: {
      type: Object,
      required: true
    },
    chartOptions: {
      type: Object,
      required: false
    }
  },
  mounted () {
    this.renderChart(this.chartData, this.chartOptions)
  }
})

// import your LineChart.js

import { defineComponent } from 'vue'
import LineChart from './path/to/LineChart.js'

export default defineComponent({
  name: 'App',
  extends: Line,
  data () {
    return {
      state: {
        chartData: {}
      }
    }
  },
  beforeMount () {
    this.handleFillData()
  },
  methods: {
    handleFillData () {
      this.state.chartData = {
        labels: ['Label 1', 'Label 2'],
        datasets: [
          {
            label: 'Data One',
            backgroundColor: '#f87979',
            data: [this.handleGetRandomInt(), this.handleGetRandomInt()]
          }
        ]
      }
    },
    handleGetRandomInt () {
      return Math.floor(Math.random() * (10 - 5 + 1)) + 10
    }
  },
  render() {
    return (
      <Fragment>
        <Chart chartData={this.state.chartData} chartOptions={this.state.chartOptions} />
        <button onClick={this.fillData}>Randomize</button>
      </Fragment>
    )
  }
})

Output

#