Skip to content

Instantly share code, notes, and snippets.

@rvanzon
Last active September 1, 2022 13:25
Show Gist options
  • Save rvanzon/096132b7b46be43659cf26360c664e9a to your computer and use it in GitHub Desktop.
Save rvanzon/096132b7b46be43659cf26360c664e9a to your computer and use it in GitHub Desktop.
A way to use vue-chartjs as a plugin of Nuxt.js

(WARNING: THIS IS OUTDATED, DON'T USE AS IS! INSTEAD CHECK OUT THE COMMENTS AT THE BOTTOM)

And check out: https://github.com/nuxt/nuxt.js/tree/dev/examples/vue-chartjs

How does this work

  1. Create a custom plugin and put it in plugins (plugins_vue-chartjs.js).
  2. Add the plugin to nuxt.config.js and set ssr to false to prevent the server to initialize it.
  3. You can use the component now just like other Vue-components. The only problem is that you get errors because the DOM-tree is out of sync (because the server misses the component)
  4. As mounted() is only called by the client (browser) we're using this to render the component only in the browser. Add showLine: false to data (so the server will not render it) and turn it to true in mounted().
  5. Use v-if to render the component. Now it won't be rendered on the server side, but it will show up in de browser.

This way also works with other Vue.js plugins

Used in this example:
npm install vue-chartjs --save
npm install chart.js --save

// just an example. A cleaner way is to wrap the showLine-stuff in a dedicated component
<template>
<div>
<my-line v-if="showLine" :data="lineData" :options="options">
</div>
</template>
<script>
export default {
data () {
return {
showLine: false
}
},
mounted () {
this.showLine = true // showLine will only be set to true on the client. This keeps the DOM-tree in sync.
},
asyncData () {
const lineData = {} // some data
const options = {} // some options
return { lineData, options }
}
}
</script>
...
/*
** Build configuration
*/
plugins: [
{ src: '~/plugins/vue-chart.js', mode: 'client' },
],
...
import Vue from 'vue'
import { Line } from 'vue-chartjs'
Vue.component('my-line', Line.extend({
props: ['data', 'options'],
mounted () {
this.renderChart(this.data, this.options)
}
}))
@piyushchauhan2011
Copy link

I feel like this pattern should be documented in Nuxt.js

@uptownhr
Copy link

uptownhr commented Jun 7, 2017

Nice!

@frankspin89
Copy link

Very Nice!

@FPierre
Copy link

FPierre commented Oct 17, 2017

Same setup, but need to use make plugin like this:

import Vue from 'vue'
import { Bar } from 'vue-chartjs'

Vue.component('portolio-chart', {
  extends: Bar,
  props: ['data', 'options'],
  mounted () {
    this.renderChart(this.data, this.options)
  }
})

Otherwise it's produce vue-chartjs.js:7 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_vue_chartjs__.Bar.extend is not a function error

@rahulrumalla
Copy link

What FPierre said. Running into the error __WEBPACK_IMPORTED_MODULE_1_vue_chartjs__.Bar.extend is not a function

Any suggestions on how to fix this, please?

@imdunkind
Copy link

imdunkind commented Nov 12, 2017

import { Line } from 'vue-chartjs'

export default {
  extends: Line,
  props: ['data', 'options'],
  mounted () {
    this.renderChart(this.data, this.options)
  }
}

try it.. plugins/vue-chartsjs.js

@Kency1013
Copy link

with error Uncaught TypeError: WEBPACK_IMPORTED_MODULE_1_vue_chartjs
try
import Vue from 'vue';
import {Line} from 'vue-chartjs';
Vue.component('line-chart', {
extends: Line,
props: ['data', 'options'],
mounted() {
this.renderChart(this.data, this.options);
}
});

@lobaak
Copy link

lobaak commented Apr 19, 2018

This was very helpful, cheers

@sergiorodenas
Copy link

This Nuxt official example is SSR working: https://github.com/nuxt/nuxt.js/tree/dev/examples/vue-chartjs

@raviasthra
Copy link

hi , charts not working in vue+nuxt.js.
package.json
"dependencies": {
"@nuxtjs/axios": "^5.3.1",
"axios": "^0.18.0",
"body-parser": "^1.18.2",
"chart.js": "^2.7.2",
"es6-promise": "^4.2.4",
"express": "^4.16.3",
"express-session": "^1.15.6",
"fs": "0.0.1-security",
"hchs-vue-charts": "^1.2.8",
"net": "^1.0.2",
"nuxt": "^1.4.0",
"vee-validate": "^2.1.0-beta.2",
"vue-chartjs": "^3.4.0",
"vue-image-compressor": "^1.0.3",
"vuetify": "^1.0.0",
"vuex": "^3.0.1",
"whatwg-fetch": "^2.0.4"
},

Pages/Dashboard.vue



Dashboard: {{ $store.state }}



<script> import { Bar } from '~/components/bar-charts.js' export default { data () { return { showLine: false, barChartData: { labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'], datasets: [ { label: 'Nuxt.js Commit Activity', backgroundColor: '#41b883', data: [40, 39, 10, 40, 39, 80, 40] } ] } } }, components: { Bar } } </script>

components/abr-charts.js
import { Bar } from 'vue-chartjs'

export default {
extends: Bar,
props: ['data', 'options'],
mounted () {
this.renderChart(this.data, this.options)
}
}

nuxt.config.js
/*
** Build configuration
/
build: {
babel: {
plugins: [
["transform-imports", {
"vuetify": {
"transform": "vuetify/es5/components/${member}",
"preventFullImport": true
}
}]
]
},
vendor: [
'~/plugins/vuetify.js',
'~plugins/vue-chartjs.js'
],
vendor: ['axios'],
extractCSS: true,
/

** Run ESLint on save
*/
extend (config, ctx) {
if (ctx.isDev && ctx.isClient) {
config.module.rules.push({
enforce: 'pre',
test: /.(js|vue)$/,
loader: 'eslint-loader',
exclude: /(node_modules)/
})
}
if (ctx.isServer) {
config.externals = [
nodeExternals({
whitelist: [/^vuetify/]
})
]
}
}
},

result empty view only showed.
pls help me to solve this.

@codehunter12345
Copy link

codehunter12345 commented Dec 4, 2019

@Kency1013 Syntax for creating chart component has been changed in the latest version (3.0.0) :

import { Line } from 'vue-chartjs'


Vue.component("my-line", {
  extends: Line,
  props: [ "options", "mydata"],
  mounted() {
    this.renderChart(this.mydata, this.options);
  }
});

And with reactiveProp There is no need for data props :

<my-line v-if="showLine" :options="options" :mydata="lineData">

@AleWasser
Copy link

For Nuxt > 2.9.0 you should use mode: 'client' in the nuxt.config.js:

 plugins: [
    {
      src: '~/plugins/vue-chart.js', mode: 'client'
    }
  ]

And to render it you should use a <client-only> tag

<client-only>
    <my-line :data="data"></my-line>
</client-only>

@Carlos-Henreis
Copy link

Help me! Unknown custom element: <my-line> - did you register the component correctly? For recursive components, make sure to provide the "name" option.e

@rvanzon
Copy link
Author

rvanzon commented Jan 9, 2021

@Carlos-Henreis are you sure you added the plugin to nuxt.config.js?

@MarcelloTheArcane
Copy link

If anyone's getting the "export 'default' (imported as 'Chart') was not found in 'chart.js' error or WEBPACK_IMPORTED_MODULE errors, downgrade your chart.js version to ^2.9.3.

@nuno-studiographene
Copy link

nuno-studiographene commented Apr 7, 2021

MarcelloTheArcane Thanks a lot! I spent 3 hours trying to figure out why it wasnt working. Your solution fixed my WEBPACK_IMPORTED_MODULE issue

Copy link

ghost commented Apr 8, 2021

@MarcelloTheArcane Thanks Dude. I spent a lot of time why WEBPACK_IMPORTED_MODULE happening I couldn't find anything. I solved

@isebarn
Copy link

isebarn commented Apr 8, 2021

For Nuxt > 2.9.0 you should use mode: 'client' in the nuxt.config.js:

 plugins: [
    {
      src: '~/plugins/vue-chart.js', mode: 'client'
    }
  ]

And to render it you should use a <client-only> tag

<client-only>
    <my-line :data="data"></my-line>
</client-only>

Thanks!

If anyone's getting the "export 'default' (imported as 'Chart') was not found in 'chart.js' error or WEBPACK_IMPORTED_MODULE errors, downgrade your chart.js version to ^2.9.3.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment