Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using data from vuex to populate a line graph #67

Closed
tlaredo opened this issue Mar 16, 2017 · 5 comments
Closed

Using data from vuex to populate a line graph #67

tlaredo opened this issue Mar 16, 2017 · 5 comments

Comments

@tlaredo
Copy link

tlaredo commented Mar 16, 2017

Expected Behavior

Hello! I'm trying to load a line chart using the reactiveProp and no data is showing on the graph for me on initial load. Please note that the chart data is stored using vuex. Here's the process that we follow:

We have two components that deal with the graph:

  1. A Course component
  2. A CourseGraph component

Process:

  1. On page load, before Course mounts, Course dispatches an action ('updatePredictionData') to initialize data in the vuex store with an API request. (the API request happens in the store)

  2. Course calls its mounted function, which calls fillData(), which populates its data with the activeCourseChartData from the getter. activeCourseChartData returns all zeros because the store wasn't finished updating from the 'updatePredictionData' action.

  3. Once the data in the store is finished updating, it should trigger the component's 'updated' function and call fillData() again.

  4. The problem is that the component's 'updated' function doesn't get called, which doesn't trigger the fillData function().

  5. The result is our graph doesn't update its data even after the computed property activeCourseChartData returns updated data

The Course component, which passes a prop to the course-graph component
template part of course component

<template>
    <div>
        <course-graph :chart-data="datacollection"></course-graph>
    </div>
</template

javascript part of course component

<script>
    export default {
        data() {
            return {
                datacollection: null,
                courseDataLoaded: false,
            }
        },
        methods: {
            fillData () {
                // we always have 560 datapoints, so we're just
                // going to create labels from 0 to 560
                var chartLabels = []
                for (var i = 0; i < 560; ++i) {
                    chartLabels.push(i)
                }
                // set datacollection
                this.datacollection = {
                    labels: chartLabels,
                    datasets: [
                        {
                        label: 'Seats Available',
                        // pull data from a getter, which returns an 
                        // array of 560 integers theoretically this should 
                        // update the data and not cause a re-render
                        data: this.activeCourseChartData, 
                        }
                    ],
                }
            },
        },
        mounted() {
            this.fillData() // on mounted, call fillData()
        },
        beforeMount() {   
            // Before the component is mounted, we dispatch 
            // an action which makes an API request
            // and sets data in the store
            this.$store.dispatch('updatePredictionData')
        },
        updated() {
            // should update datacollection when it detects a change in the store
            // (i.e. after updatePredictionData gets called)
            this.fillData()
        },
        computed: {
            // returns an array of 560 integers from the vuex store
            // returns all zeros when the store is not yet set 
            // (i.e. updatePredictionData hasn't been dispatched)
            activeCourseChartData() {
                return this.$store.getters.activeCourseChartData
            },
        },

The CourseGraph component

<script>
import { Line, mixins } from 'vue-chartjs'

export default {
  extends: Line,
    mixins: [mixins.reactiveProp],
    mounted () {
        this.renderChart(this.chartData, { responsive: true, maintainAspectRatio: false})
    },

If you're familiar with vuex and how it interacts with chart data, please lmk :)

On a side note, if the data updates, is it supposed to re-render the graph? Like cause the graph to animate from the x-axis up?

Environment

  • vue.js version: latest version
  • vue-chart.js version: latest version
@apertureless
Copy link
Owner

Hey,

well it's hard for me to debug on seeing only a few methods.
Generally vue-chartjs is working with vuex. You can find a minimal repo here: https://github.com/apertureless/vue-chartjs-vuex

Does some errors get thrown?

My first thought is, that is has to do with the limitations mentioned in the docs and in #44 which affect the mixin, because the mixin only calls a watch on chartData.

The reactiveProp Mixin is pretty simple and also not for all use-cases. Therefore you can implement a own watcher for your use-case.

You could for example create an event bus and check what in your vuex data changed.
And call the Chart.js update by your own.

You can access all Chart.js methods over this._chart

Generally if you add new datasets, you should re-render the chart and if you add only new data to an existing dataset, you can call this._chart.update()

If you're using an event bus you could listen in the component on a data:updated event or something then then call this._chart.update()

@tlaredo
Copy link
Author

tlaredo commented Mar 18, 2017

Figured out how to resolve the issue! I actually used the reactiveData mixin instead of the reactive prop and pulled data from the vuex store with a getter.

The way I fixed the issue with the chart not re-rendering after the store was somewhat hacky... When the store is initialized with data from my API endpoint, I set a bool in the store, which I access with another getter (let's call it 'chartLoaded'). In my course component, I get access to chartLoaded, then pass that down as a prop to my course-graph component. In my course-graph component, I set a watcher on chartLoaded... then when it detects that chartLoaded changed (from 0 to 1 after the store is initialized with data from my API endpoints), the watcher calls fillData() and the chart re-renders!

@tlaredo tlaredo closed this as completed Mar 18, 2017
@ivanvorona
Copy link

@tlaredo - would you mind sharing your solution if you still remember it?

@tlaredo
Copy link
Author

tlaredo commented Mar 12, 2019

@ivanvorona I'll have to check later tonight if I still have the solution

@ivanvorona
Copy link

@tlaredo I am all set for now. but thank you for reply anyway!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants