I am currently making a dashboard page and currently struggling how to render the datasets to the Bar chart. I have no problems showing static data to the chart, but when I use API data, it does not work. I read solutions about using watchers. But I am confused how to solve it if my Barchart is in another component. I have some data returning from API like: governerate: [total_sent_applications, active_members, name] which I should display. but, I guess the bar chart component is mounting to the dom before accessing the data. so, the data with bar charts appears and when reload browser suddenly disappears.
Parent Component:
<template>
<div class="row">
<div class="col-xl-12 col-md-6 col-sm-12">
<bar-chart
:active-members="active"
:name="governorateName"
:total-sent-applications="sent_applications"
/>
</div>
</div>
</template>
<script>
import BarChart from "@/components/UI/BarChart.vue";
export default {
components: {
AppCard,
BarChart,
},
data() {
return {
chartData: [],
active: [],
governorateName: [],
sent_applications: [],
};
},
created() {
this.chartData = this.$store
.dispatch("home/fetchAllData") // function that loads data from api
.then((response) => { // the returned data from api
this.sent_applications = response.data.data.governerate.map(
(el) => el.total_sent_applications
);
this.governorateName = response.data.data.governerate.map(
(el) => el.name_ar
);
this.active = response.data.data.governerate.map(
(el) => el.active_members
);
})
},
};
</script>
Child Component: (BarChart.vue)
<template>
<div class="card">
<div
class="
card-header
d-flex
justify-content-between
align-items-sm-center align-items-start
flex-sm-row flex-column
"
></div>
<div class="card-body">
<canvas
id="myChart"
class="bar-chart-ex chartjs"
data-height="600"
></canvas>
</div>
</div>
</template>
<script>
import Chart from "chart.js";
export default {
name: "BarChart",
props: {
activeMembers: {
type: Array,
default: null,
},
name: {
type: Array,
default: null,
},
totalSentApplications: {
type: Array,
default: null,
},
},
mounted() {
const ctx = document.getElementById("myChart").getContext("2d");
const chart = new Chart(ctx, {
type: "bar",
data: {
labels: this.name,
datasets: [
{
label:
this.$t("total_sent_applications") || "Total Sent Applications",
data: this.totalSentApplications,
backgroundColor: "rgba(71, 183, 132, 0.5)",
borderColor: "#47b784",
borderWidth: 1,
},
{
label: this.$t("active_members") || "Active Members",
data: this.activeMembers,
backgroundColor: "rgba(255, 255, 0, 0.5)",
borderColor: "#255255",
borderWidth: 1,
},
],
},
options: {
barValueSpacing: 10,
responsive: true,
lineTension: 1,
scales: {
xAxes: [
{
label: "chart",
ticks: {
beginAtZero: false,
padding: 5,
},
},
],
yAxes: [
{
label: "chart",
ticks: {
beginAtZero: false,
padding: 10,
},
},
],
},
},
});
},
};
</script>
If you only need to fetch data once and then have it displayed in the chart you can achieve it with v-if or with the Vue key attribute. The below code snipped should work for you.
<template>
<div class="row">
<div class="col-xl-12 col-md-6 col-sm-12">
<bar-chart
:key="sent_applications.length"
v-if="dataFetched"
:active-members="active"
:name="governorateName"
:total-sent-applications="sent_applications"
/>
</div>
</div>
</template>
<script>
import BarChart from "@/components/UI/BarChart.vue";
export default {
components: {
AppCard,
BarChart,
},
data() {
return {
chartData: [],
active: [],
governorateName: [],
sent_applications: [],
dataFetched: false
};
},
created() {
this.chartData = this.$store
.dispatch("home/fetchAllData") // function that loads data from api
.then((response) => { // the returned data from api
this.sent_applications = response.data.data.governerate.map(
(el) => el.total_sent_applications
);
this.governorateName = response.data.data.governerate.map(
(el) => el.name_ar
);
this.active = response.data.data.governerate.map(
(el) => el.active_members
);
this.dataFetched = true
})
},
};
</script>
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.