Vue-chartjs: Pass Reactive data into Scatterplot

Created on 19 Mar 2017  ·  6Comments  ·  Source: apertureless/vue-chartjs

Is it possible to create a line chart that uses my own predefined x & y axis data? Currently, the line chart accepts an array of values that correspond to the array of labels. However, Chart.js allows data to be declared like this:
data: {
datasets: [{
label: 'Scatter Dataset',
data: [{x: -10,y: 0}, {x: 0,y: 10}]
}]

Anyways, is it possible to do this with Vue-chartjs? I have been attempting it but get a "me.ticks.map is not a function" typeError.

☂ feature-request ❓ question

Most helpful comment

Thanks @apertureless that was super helpful.
If anyone comes around this problem and is looking for help, I suggest doing this:
1) Create a new prop to pass into lineChart

<div class="lineChart">
    <line-chart :chart-data="obj" :test="datasetsfull"></line-chart>
  </div>

2) Your update will occur in a computed function called "datasetsfull"

  computed: {
    datasetsfull () {
      return {
        label: 'graph',
        type: 'line',
        datasets: [
          {
            label: '/data',
            backgroundColor: '#E1F5CA',
            data: this.GetLineGraphData1 // a getter from Vuex
          },
          {
            label: '/analytics',
            backgroundColor: '#67C6AE',
            data: this.GetLineGraphData2
          }
        ]
      }
    }

3) Make sure to call your action through a "Mounted" or "beforeCreated" function

beforeCreate () {
  this.$store.dispatch('FETCH_LINE_GRAPH')
},

4) Now your Chart.js file can look something like this, and it should work

import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins

export default Line.extend({
  mixins: [reactiveProp],
  props: ['test', 'options'],
  data () {
    return {
      obj: {
        label: 'graph',
        type: 'line',
        datasets: [
          {
            label: '/data',
            backgroundColor: '#E1F5CA',
            data: [ //This is just initial data I pass to make sure it renders as a Scatterplot
              {
                x: 5,
                y: 6
              },
              {
                x: 7,
                y: 8
              }
            ]
          }
        ]
      }
    }
  },
  mounted () {
    if (this.chartData) {
      this.renderChart(this.obj, {responsive: true, maintainAspectRatio: false})
    }
  },
  watch: {
    test: function () {
      this.renderChart(this.test, { //Right here is where the new data will be rendered 
        responsive: true,
        maintainAspectRatio: true,
        scales: {
          yAxes: [{
            ticks: {
              min: 90000000,
              max: 170000000
            }
          }],
          xAxes: [{
            position: 'bottom',
            ticks: {
              min: 1,
              max: 100000000
            }
          }]
        }
      })
    }
  }
})

All 6 comments

Can you post a jsfiddle or codepen for reproduction?

Beacause for me it's working.

scatter line

Ah, the problem is that I am passing in an array of objects through a reactiveProp. Is there a work around? The problem is that I have around 2000 objects with different x and y values being called in from an API.

Not right now.
I will check if I can modify the mixin to work with both.
An alternative would be, to implement an update mechanism by yourself. Own mixin or something event based. Because you have access to the chart.js instance and can call update() by yourself.

The mixin is not the best fit for all use cases, because it depends on how you populate your data.
There are some limitation for the watcher and reactive data.

Hey @sdzharkov

well I tried a few things out, however I could not get it working.
The point is that because of the limitations of vue.$watch

The watcher does not see any changes of chartData and if you have objects in your data which are nested it's even worse 🙈 . Thats also why the Bubble Chart will not work with the reactive Mixin.

It accepts the following data { x: 20, y: 30, r: 15 } but if you push new data the vue watcher does not recognize it.

However I could not reproduce the error you got. 🤔

The mixins are kind of hacky, because Chart.js does not support live data nor automatic chart updating on new data.

What you could do, is like said before to trigger the update by yourself. You can access the chart instance at this._chart and call update()

There are many ways how to do it. You could use like said before an event bus or something.

Thanks @apertureless that was super helpful.
If anyone comes around this problem and is looking for help, I suggest doing this:
1) Create a new prop to pass into lineChart

<div class="lineChart">
    <line-chart :chart-data="obj" :test="datasetsfull"></line-chart>
  </div>

2) Your update will occur in a computed function called "datasetsfull"

  computed: {
    datasetsfull () {
      return {
        label: 'graph',
        type: 'line',
        datasets: [
          {
            label: '/data',
            backgroundColor: '#E1F5CA',
            data: this.GetLineGraphData1 // a getter from Vuex
          },
          {
            label: '/analytics',
            backgroundColor: '#67C6AE',
            data: this.GetLineGraphData2
          }
        ]
      }
    }

3) Make sure to call your action through a "Mounted" or "beforeCreated" function

beforeCreate () {
  this.$store.dispatch('FETCH_LINE_GRAPH')
},

4) Now your Chart.js file can look something like this, and it should work

import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins

export default Line.extend({
  mixins: [reactiveProp],
  props: ['test', 'options'],
  data () {
    return {
      obj: {
        label: 'graph',
        type: 'line',
        datasets: [
          {
            label: '/data',
            backgroundColor: '#E1F5CA',
            data: [ //This is just initial data I pass to make sure it renders as a Scatterplot
              {
                x: 5,
                y: 6
              },
              {
                x: 7,
                y: 8
              }
            ]
          }
        ]
      }
    }
  },
  mounted () {
    if (this.chartData) {
      this.renderChart(this.obj, {responsive: true, maintainAspectRatio: false})
    }
  },
  watch: {
    test: function () {
      this.renderChart(this.test, { //Right here is where the new data will be rendered 
        responsive: true,
        maintainAspectRatio: true,
        scales: {
          yAxes: [{
            ticks: {
              min: 90000000,
              max: 170000000
            }
          }],
          xAxes: [{
            position: 'bottom',
            ticks: {
              min: 1,
              max: 100000000
            }
          }]
        }
      })
    }
  }
})

Cool, thanks for the example and workaround! May help some people!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kurbar picture kurbar  ·  4Comments

Sykomaniac picture Sykomaniac  ·  3Comments

rzb picture rzb  ·  4Comments

bdeanindy picture bdeanindy  ·  3Comments

Scalpel78 picture Scalpel78  ·  4Comments