Search code examples
javascriptvue.jschart.jsvue-clivue-cli-3

How to use computed property with data from JSON in data object for time axis in Vue using Chart.js


I'm trying to create a chart with a time axis in Vue using Chart.js. When I set the data right in the Data object like so, everything works correctly:

chartData: {
    datasets: [
        {
            backgroundColor: '#ED645A',
            borderColor: '#ED645A',
            fill: false,
            data: [
                {
                    t: new Date("1998-1-1"),
                    y: 7.1
                },
                {
                    t: new Date("1998-2-1"),
                    y: 8.4
                },
                {
                    t: new Date("1998-3-1"),
                    y: 18.5
                },
                {
                    t: new Date("1998-4-1"),
                    y: 16.2
                },
                {
                    t: new Date("1998-5-1"),
                    y: 18.4
                }
            ]
        }
    ]
},

But when I'm trying to load the data from JSON and form the datasets object in computed property, like so, it doesn't work:

import pureSecondDatasetJson from "../assets/pureSecondDataset.json"

...

export default {

...

data () {
    return {
        pureSecondDataset: pureSecondDatasetJson,
        charts: [
            chartData: {
            datasets: this.foo
},

...

computed: {
    foo() {
        var plotData = []
        for (var i=0; i<this.pureSecondDataset.length; i++) {        
            plotData.push({t: new Date(this.pureSecondDataset[i].t), y: this.pureSecondDataset[i].y})
        }
        var chartData = [
            {
                backgroundColor: '#ED645A',
                borderColor: '#ED645A',
                fill: false,
                data: plotData
            }
        ];
        return chartData
    }
}

The object, created in computed seems the same as the one, which put directly, so why it doesn;t work?


Solution

  • You shouldn't try access a computed property from your data as explained on the Vue Forum.

    the data is evaluated before the computed array

    I would advise changing your computed property to something like below and then use that as your chart data:

    foo() {
        var plotData = []
        for (var i=0; i<this.pureSecondDataset.length; i++)        
            plotData.push({t: new Date(this.pureSecondDataset[i].t), y: this.pureSecondDataset[i].y})
    
        return {
            chartData: {
                datasets:[{
                    backgroundColor: '#ED645A',
                    borderColor: '#ED645A',
                    fill: false,
                    data: plotData
                }]
            }
        }
    }
    

    I've added a fiddle to show how you can do this by not using the computed property in data. While I was making the fiddle I found that for a proper line graph you need to have a labels property for the x-values otherwise you can use type: scatter and drawLine:true to specify the x and y values together. Chart.js - Plot line graph with X , Y coordinates

    new Vue({
      el: "#app",
      data: () => {
        return {
          plotData: [{
            x: 1,
            y: 1
          }, {
            x: 2,
            y: 2
          }, {
            x: 3,
            y: 3
          }]
        }
      },
      computed: {
        foo() {
          return {
            type: 'scatter',
            data: {
              datasets: [{
                showLine: true,
                label: 'My First dataset',
                backgroundColor: 'rgb(255, 99, 132)',
                borderColor: 'rgb(255, 99, 132)',
                data: this.plotData
              }]
            }
          }
        }
      },
      mounted() {
        var ctx = document.getElementById('chart').getContext('2d');
        new Chart(ctx, this.foo);
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chart.js@2.8.0"></script>
    <div id="app">
      <canvas id="chart" width="400" height="400"></canvas>
    </div>