Vue-chartjs: Uncaught TypeError: _c is not a function

Created on 17 Dec 2016  路  3Comments  路  Source: apertureless/vue-chartjs

Hello, here's what I did :

<template>
  <canvas id="myChart" width="400" height="400"></canvas>
</template>

<script>
/*eslint-disable*/
import VueCharts from 'vue-chartjs'
import { Bar, Line } from 'vue-chartjs'

export default Bar.extend({
  name: 'dashboard',
  mounted: function () {
    this.renderChart({
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      datasets: [
        {
          label: 'GitHub Commits',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
        }
      ]
    })
  }
})
</script>

And this is the error I get in the console:

Vue warn]: Property or method "_c" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. 
(found in component <dashboard> at /Users/gplus/vm/weather-dashboard/src/components/dashboard.vue)
Lr
2016-12-17 11:17:11.918 (unknown) [Vue warn]: Error when rendering component <dashboard> at /Users/gplus/vm/weather-dashboard/src/components/dashboard.vue: 
Lr
2016-12-17 11:17:11.918 localhost/:7 Uncaught TypeError: _c is not a function
    at Proxy.render (eval at <anonymous> (app.js:756), <anonymous>:2:10)
    at o.Ce.t._render (eval at <anonymous> (app.js:732), <anonymous>:7:17515)
    at o.eval (eval at <anonymous> (app.js:732), <anonymous>:7:11842)
    at Kr.get (eval at <anonymous> (app.js:732), <anonymous>:9:4428)
    at new Kr (eval at <anonymous> (app.js:732), <anonymous>:9:4367)
    at o.e._mount (eval at <anonymous> (app.js:732), <anonymous>:7:11810)
    at o.ze.$mount (eval at <anonymous> (app.js:732), <anonymous>:9:15134)
    at o.ze.$mount (eval at <anonymous> (app.js:732), <anonymous>:9:18888)
    at init (eval at <anonymous> (app.js:612), <anonymous>:2500:11)
    at createComponent (eval at <anonymous> (app.js:612), <anonymous>:4052:9)

Most helpful comment

Hey @gkatsanos

there are a few errors in your example.

1. You don't need to import both

import VueCharts from 'vue-chartjs'
import { Bar, Line } from 'vue-chartjs'

If you do import VueCharts from 'vue-chartjs', you can access all chart types over the VueCharts object. For example VueCharts.Bar or VueCharts.Doughnut

However most of the time, your component will only represent one chart type. So thats why you can import only the nessasary modules

import { Bar } from 'vue-chartjs'

2. Template

You don't need the template tag with the canvas inside of it.
The template is included into the base charts you import over import { Bar } from 'vue-chartjs'

Thats why you *.extend() it.

3. Vue Single File component

As far as I remeber, you can't do this export default Bar.extend({}) in vue single file components. If you really need the single file components, there is a property you can use extends: <component> it was mentioned in #12

// MyChart.vue
<template>
...
</template>

<script>
import {Bar} from 'vue-chartjs'

export default {
  extends: Bar
  data () { ... }
}

</script>

However as you don't need the template tag and styling, you can make it a simple js file.

4. Fixed example

// YourChart.js

import { Bar } from 'vue-chartjs'

export default Bar.extend({
  name: 'dashboard',
  mounted: function () {
    this.renderChart({
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      datasets: [
        {
          label: 'GitHub Commits',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
        }
      ]
    })
  }
})

And then you can import your component into other vue components

//Dasboard.vue

<template>
  <div class="container">
    <your-chart :width="400" :height="400"></your-chart>
  </div>
</template>

<script>
  import YourChart from './your-chart.js'

  export default {
      components: { YourChart }, 
      data () {
        ....
      }
  }
</script>

<style>
  .container { max-width: 80rem; margin: 0 auto;}
</style>

All 3 comments

Hey @gkatsanos

there are a few errors in your example.

1. You don't need to import both

import VueCharts from 'vue-chartjs'
import { Bar, Line } from 'vue-chartjs'

If you do import VueCharts from 'vue-chartjs', you can access all chart types over the VueCharts object. For example VueCharts.Bar or VueCharts.Doughnut

However most of the time, your component will only represent one chart type. So thats why you can import only the nessasary modules

import { Bar } from 'vue-chartjs'

2. Template

You don't need the template tag with the canvas inside of it.
The template is included into the base charts you import over import { Bar } from 'vue-chartjs'

Thats why you *.extend() it.

3. Vue Single File component

As far as I remeber, you can't do this export default Bar.extend({}) in vue single file components. If you really need the single file components, there is a property you can use extends: <component> it was mentioned in #12

// MyChart.vue
<template>
...
</template>

<script>
import {Bar} from 'vue-chartjs'

export default {
  extends: Bar
  data () { ... }
}

</script>

However as you don't need the template tag and styling, you can make it a simple js file.

4. Fixed example

// YourChart.js

import { Bar } from 'vue-chartjs'

export default Bar.extend({
  name: 'dashboard',
  mounted: function () {
    this.renderChart({
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      datasets: [
        {
          label: 'GitHub Commits',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
        }
      ]
    })
  }
})

And then you can import your component into other vue components

//Dasboard.vue

<template>
  <div class="container">
    <your-chart :width="400" :height="400"></your-chart>
  </div>
</template>

<script>
  import YourChart from './your-chart.js'

  export default {
      components: { YourChart }, 
      data () {
        ....
      }
  }
</script>

<style>
  .container { max-width: 80rem; margin: 0 auto;}
</style>

Thank you for the kind and super long reply, I appreciate it.
I have a rather stupid question : Why the vue wrapper over the actual library itself?
In the end I realized my problem was not initializing the chart inside mounted ..

Well, like with nearly all wrappers and bindings in vue that work with third party plugins or libs, there is no real benefit.

The pros are that it works simply out of the box. And is a predefined component.
You can import it, pass the data and thats it. You don't need to care about the canvas, ids etc.

I created it for a side project of mine and I was too lazy to always replicate the code. Create a canvas, create a new chartjs instance etc. So I added a small layer of abstraction.

Its good, if you want something fast up and running. However if you need more control and have very specific use cases, it's always better to implement them by yourself.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bdeanindy picture bdeanindy  路  3Comments

egorzekov picture egorzekov  路  4Comments

Sykomaniac picture Sykomaniac  路  3Comments

sergeynilov picture sergeynilov  路  3Comments

LeeLenaleee picture LeeLenaleee  路  3Comments