Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering C3 chart using Nuxt

Background

I am currently working with Nuxt and need to render some C3 charts in a vue component. C3 is calling Window in the library so it throws an error on the C3 library import statement.

window is not defined

I know this is happening because it is server side rendering and it needs the browser to access window. I also know I need to tell Nuxt to allow this specific component, or part of the component to be rendered once it is in the browser.

I know C3 is built on top of D3 so I figured I would try to get that to load as well. I read that this is how you handle non server side rendered libraries.

Example Code

nuxt.config.js

 plugins: [
    { src: '~plugins/d3', ssr: false },
    { src: '~plugins/c3', ssr: false },
  ],

build: {
    vendor: ['d3', 'c3'],
  },

/plugins/d3.js

import * as d3 from 'd3';

export default d3;

/plugins/c3.js

import c3 from 'c3';

export default c3;

Once I add these configurations I then move to the component I want to use them in,

import * as d3 from 'd3';
import c3 from 'c3';
import 'c3/c3.css';

This allows D3 to work. But when I import C3, it still throws the same error. So, I read that I should try this,

   let c3 = null;
    if (process.browser) {
        c3 = require('c3');
    }

That still does not work and C3 still throws an error. The new error is,

c3 is not defined.

I am rendering the C3 Charts in mount

  mounted() {
    const chart = c3.generate({
      bindto: '#result-chart',
      data: {
        columns: [['data1', 30], ['data2', 120]],
        type: 'pie',
      },
    });
  },

Question

As I understand it now the if statement is working and allowing the page to continue rendering while skipping over the import. But now that it has skipped over it, how do I actually render the graph once the page is available to the browser? With my current implementation C3 is never in scope.

One more error I saw at one point was generator is undefined. I could not figure out where that was coming from, but just in case that helps.

like image 859
wuno Avatar asked May 11 '18 18:05

wuno


1 Answers

From your description you import d3 and c3 twice, by using nuxt plugin and in your component. I think you could do it in the following way:

/plugins/chart.js

import * as d3 from 'd3';
import c3 from 'c3';

export default (ctx, inject) => {
  inject("d3", d3);
  inject("c3", c3);
};

/nuxt.config.js

plugins: [
  { src: "~/plugins/chart", ssr: false }
]

inject method will insert d3 and c3 object into nuxt context, so that you can call them using this.$d3 and this.$c3, for instance:

  mounted() {
    const chart = this.$c3.generate({
      bindto: '#result-chart',
      data: {
        columns: [['data1', 30], ['data2', 120]],
        type: 'pie',
      },
    });
  },
like image 101
Jefry Dewangga Avatar answered Oct 20 '22 20:10

Jefry Dewangga