fastBreak
fastBreak

Reputation: 21

Change data and update bar chart in vue-chartjs

I want to switch the chart from using the data stored in one object property to another (from data stored under the key value to the key value2) by clicking a button (@click).

I don't know how to use @click for updating the data.

I'm using Axios to get the data using async await.

My JSON data:

// Pulled from 
// https://raw.githubusercontent.com/narudolimudom/Hospital/main/examplefile.json

[
   {
      "id": 1,
      "name": "A",
      "value": 20,
      "value2": 50,
      "value3": "90",
      "value4": "100"
   },
   {
      "id": 2,
      "name": "B",
      "value": 47,
      "value2": 48,
      "value3": "66",
      "value4": "87"
   },
   . . .
]

I want to go from using resp.data[index].value in my chart to using resp.data[index].value2.


This is my code:

Test.vue

<template>
  <div class="container">
    <button>Click</button>
    <barchart v-if="loaded" :chartdata="chartData" :options="options" />
  </div>
</template>

<script>
import axios from "axios";
import barchart from "./Render.vue";

export default {
  name: "LineChartContainer",
  components: { barchart },
  data: () => ({
    loaded: false,
    chartData: {
      labels: [],
      datasets: [
        {
          label: "Bar Chart",
          borderWidth: 1,
          pointBorderColor: "#2554FF",
          data: [],
        },
      ],
    },
    options: {.....},
  }),
  async mounted() {
    this.loaded = false;
    try {
      const resp = await axios.get(
        "https://raw.githubusercontent.com/narudolimudom/Hospital/main/examplefile.json"
      );
      for (let index = 0; index < resp.data.length; index++) {
        this.chartData.labels.push(resp.data[index].name);
        this.chartData.datasets[0].data.push(resp.data[index].value);
      }
      this.loaded = true;
    } catch (e) {
      console.error(e);
    }
  },
};
</script>

Render.vue

<script>
import { Bar } from "vue-chartjs";

export default {
  extends: Bar,
  props: {
    chartdata: {
      type: Object,
      default: null,
    },
    options: {
      type: Object,
      default: null,
    },
  },
  mounted() {
    this.renderChart(this.chartdata, this.options);
  },
};
</script>

Upvotes: 2

Views: 1503

Answers (1)

Fabian Zimbalev
Fabian Zimbalev

Reputation: 553

Simply introduce a new property that defines which value you want to use and load the data using that one instead of your fixed ".value" property.

I have not tested the below code, I just changed your snippet to clarify my approach

<template>
  <div class="container">
    <!-- toggle the selectedProp when ever you click the buttons -->
    <button @click="selectedProp = 'value'">Use value</button>
    <button @click="selectedProp = 'value2'">Use value2</button>
    <button @click="selectedProp = 'value3'">Use value3</button>
    <button @click="selectedProp = 'value4'">Use value4</button>
    <barchart v-if="loaded" :chartdata="chartData" :options="options" />
  </div>
</template>

<script>
import axios from "axios";
import barchart from "./Render.vue";

export default {
  name: "LineChartContainer",
  components: { barchart },
  data: () => ({
    loaded: false,
    selectedProp: 'value',
    chartData: {
      labels: [],
      datasets: [
        {
          label: "Bar Chart",
          borderWidth: 1,
          pointBorderColor: "#2554FF",
          data: [],
        },
      ],
    },
    options: {.....},
  }),
  async mounted() {
    this.loaded = false;
    try {
      const resp = await axios.get(
        "https://raw.githubusercontent.com/narudolimudom/Hospital/main/examplefile.json"
      );
      
      // Get all the labels from the response
      this.chartData.labels = resp.data.map(i => i.name)      
      
      // Get all the data from the response 
      // using [this.selectedProp] to get the variable field selector
      this.chartData.datasets[0].data = resp.data.map(i => i[this.selectedProp])
      this.loaded = true;
    } catch (e) {
      console.error(e);
    }
  },
};
</script>

Please be aware that you might have to refresh the bar, depending on if it is reactive on the changes on chartData or not.

Upvotes: 1

Related Questions