简体   繁体   中英

Update google chart when state change - vuex

I'm doing a reporting page, where several graphs will appear. When you enter the page, it makes a request to receive all the default information by the API. The idea is to, afterwards, allow the user to select some filters based on inputs.

example: initial - all results / with filters - some results.

To implement this, I'm using vuejs to make the components, vuex to save the information and the google charts to make the charts.

My problem is that when I implement some filter the graphics are not updating even though the state updates. I put a watcher, to check if the state undergoes changes, but only enters when it is created.

my code -

vuex -

import axios from 'axios';

const state = {
    dataChart: {}
}

const mutations = {
    'ADD_DATA_CHART'(state, data) {
        state.dataChart[data.key] = [];

        [].forEach.call(data.states, (s, i) => {
            let obj = {};
            obj.name = s;
            obj.data = [];

            [].forEach.call(data.value, d => {
                obj.data.push([d.name, d[data.keys[i]].toFixed(2)]);
            });
            state.dataChart[data.key].push(obj);
        });
    }
}

const actions = {
    fetchReporting({state, commit}, response) {
        axios.post(response.endpoint, response.formData)
            .then(({data}) => {
                commit('ADD_DATA_CHART', {key: response.chart, value: data, states: response.states, keys: response.keys})
            }).catch(err => {
                console.log(err);
            });
    }
}

const getters = {
     dataChart: state => state.dataChart
}


export default {
    state,
    mutations,
    actions,
    getters
}

component -

<template>
    <div class="box-content-white">
        <div class="title">Chart</div>
        <div id="stackedChart"></div>
    </div>
</template>
<script>
    import { mapGetters } from 'vuex';
    import { mapActions } from 'vuex';

    export default {
        props: {
            endpoint: String,
            chart: String,
            states: Array,
            keys: Array
        },
        data() {
            return {
                 data: []
            }
        },
        methods: {
            ...mapActions({
                fetchReporting: 'fetchReporting'
            }),
            loadChart() {
                google.charts.load('current', {'packages':['corechart'],'language': 'pt'});
                google.charts.setOnLoadCallback(this.drawChart);

            },
            drawChart() {
                var stackedChart = new google.visualization.DataTable();
                stackedChart.addColumn('string', this.states[0]);
                stackedChart.addColumn('number', this.states[1]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
                stackedChart.addColumn('number', this.states[2]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});
                stackedChart.addColumn('number', this.states[3]);
                stackedChart.addColumn({'type': 'string', 'role': 'tooltip', 'p': {'html': true}});

                stackedChart.addRows(this.data);

                var options = {
                        width: '100%',
                        height: 600,
                        chartArea: {width: '90%', height: '60%', left: 120},
                        isStacked: true,
                        colors: ['#e6a8b9','#cc5173', '#901c3c'],
                        tooltip: { isHtml: true },
                        legend: { position: 'bottom', alignment: 'start' },
                        animation: {
                            duration: 1000,
                            easing: 'out',
                            startup: true
                        }
                    };

                new google.visualization.ColumnChart(document.getElementById('stackedChart')).draw(stackedChart, options);
            },
            drawHtmlTooltip(message,  message2,  message3,  message4, url) {
                return `<div class="content">
                            <div class="img">
                                <img src="url" alt="Cliente">
                            </div>
                            <div class="text">
                                <div><span class="info">Message</div>
                                <div><span class="info">Message2</div>
                                <div><span class="info">Message3</div>
                                <div><span class="info">Message4</div>
                            </div>
                        </div>`;
            },
            mountData() {
                [].forEach.call(this.dataChart[this.chart], d => {

                    let htmlTooltip = this.drawHtmlTooltip(message, message2, message3, message4, url);
                    this.data.push([ // * it is necessary to repeat the tooltip, so that it is uniform in all bars
                        d.name,
                        parseInt(value),
                        htmlTooltip,
                        parseInt(value2),
                        htmlTooltip,
                        parseInt(value3),
                        htmlTooltip
                    ]);
                });

                this.loadChart();
            }
        },
        mounted() {
            this.fetchReporting({endpoint: this.endpoint, chart: this.chart, formData: { state: 'negotiation' }})
            .then(response => {
                this.mountData();
            }, error => {
                console.log(error)
            });

        },
        computed: {
            ...mapGetters({
                dataChart: 'dataChart'
            })
        },
        watch: {
            dataChart:  {
                immediate: true,              // so this runs initially
                deep: true,                   // so it detects changes to properties only
                handler(newVal, oldVal) {
                    console.log('selectedItem changed!', oldVal, '-->', newVal);
                }
            }
        }
    }
</script>

I am without solutions, do you have any suggestions to solve this problem?

To make state.dataChart reactive, you need to assign it to a new object reference.

ES6 syntax:

const mutations = {
    'ADD_DATA_CHART'(state, data) {
        var newDataItem = []
        [].forEach.call(data.states, (s, i) => {
            let obj = {};
            obj.name = s;
            obj.data = [];

            [].forEach.call(data.value, d => {
                obj.data.push([d.name, d[data.keys[i]].toFixed(2)]);
            });
            newDataItem.push(obj);
        });
        state.dataChart = {
          ...state.dataChart,
          [data.key]: newDataItem
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM