How to update data to pie chart using vue-apexcharts - api

I want to create pie-chart with vue-apexcharts. I had data from API but I don't know how to update the chart's data.
mounted() {
axios
.get("/data/episodes.json")
.then(response => {
console.log(response);
});
}
The chart I want to create is like this

Here is my understanding on doing, ...
first you have to define the data and option values of chart.
components: {
apexchart: VueApexCharts,
},
data: {
series: [],
chartOptions: {
chart: {
width: 380,
type: "pie",
},
labels: [],
responsive: [
{
breakpoint: 480,
options: {
chart: {
width: 200,
},
legend: {
position: "bottom",
},
},
},
],
},
},
Now on mount you have call your api to get the data and update the chart information. like this ...
I'm thinking of you server would return an array of objects having value and key.
mounted() {
axios.get("/data/episodes.json").then((response) => {
for (let i = 0; i < response.data.length; i++) {
this.data.series.push(response.data[i].value);
this.data.chartOptions.labels.push(response.data[i].key);
}
});
},
Finally, you have to add the chart component to the vue template. like this.
<div id="chart">
<apexchart type="pie" width="380" :options="chartOptions" :series="series"></apexchart>
</div>
Done,
Ask me if it is not clear for you.

Related

Vue-chartjs not rendering chart until page resize

I am using vue-chartjs to create charts for my application. I am passing the chartData as a prop. My chart doesn't render at first but does when I resize the window. Here is my code. First the chart component:
<script>
import { Doughnut, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;
export default {
extends: Doughnut,
mixins: [reactiveProp],
mounted() {
this.render();
},
methods: {
render() {
console.log(this.chartData)
let options = {
responsive: true,
maintainAspectRatio: false,
legend: {
display: false,
},
};
this.renderChart(this.chartData, options);
},
},
};
</script>
Now here is the code from the component where the chart is displayed:
template part
<v-container>
<ProjectDoughnutChart :chart-data="chartData" />
</v-container>
script part
components: {
ProjectDoughnutChart,
},
data() {
return {
chartData: {
labels: [],
datasets: [
{
backgroundColor: [],
hoverBackgroundColor: [],
data: [],
},
],
},
};
},
setChartsTimesheets() {
this.timesheets.forEach((timesheet) => {
let typeTotal = 0;
this.timesheets
.filter((timesheet1) => timesheet1.type==timesheet.type)
.forEach((timesheet1) => {
typeTotal+=timesheet1.billableAmount;
});
if (this.chartData.labels.indexOf(timesheet.type) === -1) {
let colors = this.getTaskColors(timesheet.type);
this.chartData.labels.push(timesheet.type);
this.chartData.datasets[0].data.push(typeTotal);
this.chartData.datasets[0].backgroundColor.push(colors.color);
this.chartData.datasets[0].hoverBackgroundColor.push(colors.hover);
}
});
},
Solved the problem using a similar solution as "Chart with API data" from the documentation.
TL;DR: Adding a v-if on the chart
For people, that have similar problem, but not using vue.js or the official solution doesnt cut it. I had to chart.update() the graph to show values, that were added after the graph was created.
See the example. If you comment the chart.update() line, the graph will not refresh until the window is resized.
let chart = new Chart(document.getElementById("chart"), {
type: "line",
data: {
labels: ["a", "b", "c", "d", "e", "f"],
datasets: [{
label: 'Dataset 1',
data: [1, 5, 12, 8, 2, 3],
borderColor: 'green',
}]
},
options: {
interaction: {
mode: 'index',
intersect: true,
},
stacked: false,
responsive: true,
}
});
// adding data to graph after it was created (like data from API or so...)
chart.data.labels.push("new data");
chart.data.datasets[0].data.push(9);
// with chart.update(), the changes are shown right away
// without chart.update(), you need to resize window first
chart.update();
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.min.js"></script>
<canvas id="chart"></canvas>

Vue chartjs is not rendering from API

I have an API that gives me data about certain things. With that data, I would like to render my chart dynamically. However, when I use that API in the created() segment, it does not get rendered. But if I shift my data to hardcode it in the data() segment, it works. May I seek advice here?
export default {
extends: Line,
data() {
return {
lineChartOptions: {
maintainAspectRatio: false,
responsive: true,
scales: { yAxes: [{ ticks: { beginAtZero: true }, gridLines: { display: true } }], xAxes: [{ gridLines: { display: false } }] },
legend: {
display: true,
},
},
lineChartData: [],
};
},
created() {
axios
.get("someurl")
.then((response) => {
let responseData = response.data;
let lineDataset = [];
for (let i = 0; i < responseData.pidList.length; i++) {
lineDataset.push({
label: responseData.pidList[i],
backgroundColor: "#2554FF",
data: 2000,
});
}
console.log(lineDataset);
this.lineChartData = { labels: ["2020", "2021"], datasets: { lineDataset } };
})
.catch(function(error) {
console.log(error);
});
},
mounted() {
this.renderChart(this.lineChartData, this.lineChartOptions);
},
};
vue-chartjs does not live update by default, this is because chart.js does not support it. To make it live update you will need to add the reactiveProp mixin as described in the documentation: https://vue-chartjs.org/guide/#updating-charts

How to correctly pass array with data to a chart from the VueApexCharts library in vue3?

I am writing a small covid project and trying to plot confirmed infection data using ApexCharts, but the graph is not showing. I enter the data from vuex in two tables. The data is valid however it comes from api and sa in the proxy object. What am I doing wrong? (I am using ApexCharts because vue Chartjs is not compatible with vue 3).
<template>
<apexchart width="500" type="bar" :options="options" :series="series"></apexchart>
</template>
<script>
import VueApexCharts from "vue3-apexcharts";
export default {
components: {
apexchart: VueApexCharts,
},
data(){
return {
series: [],
options: {
chart: {
type: "bar",
height: 400,
stacked: true
},
plotOptions: {
bar: {
horizontal: false
}
},
dataLabels: {
enabled: false
},
tooltip: {
shared: true,
followCursor: true
},
stroke: {
width: 1,
colors: ["#fff"]
},
fill: {
opacity: 1
},
legend: {
position: "top",
horizontalAlign: "center",
offsetX: 40
},
colors: ["rgb(95, 193, 215)", "rgb(226, 37, 43)", "rgb(94, 181, 89)"]
}
};
},
computed: {
getDate(){
return this.$store.getters['chart/getDate'];
},
getConfirmed(){
return this.$store.getters['chart/getConfirmed'];
}
},
methods: {
fillDate(){
this.options = {
xaxis: {
categories: this.getDate
}
}
this.series = [
{
name: 'Confirmed',
data: this.getConfirmed
}
];
}
},
async mounted() {
await this.fillDate();
}
}
The data from the vuex store are two arrays.
Proxy
[[Handler]]: Object
[[Target]]: Array(45)
[[IsRevoked]]: false
Instead of using mounted hook and method try to watch the computed properties then update the data based on that ones:
computed: {
getDate(){
return this.$store.getters['chart/getDate'];
},
getConfirmed(){
return this.$store.getters['chart/getConfirmed'];
}
},
watch:{
getDate:{
handler(newVal){
this.options = {
xaxis: {
categories: this.getDate
}
},
deep:true
},
getConfirmed:{
handler(newVal){
this.series = [
{
name: 'Confirmed',
data: this.getConfirmed
}
];
},
deep:true
}
}

How should data be structured for lineplots with vue/chart.js

I am retrieving data from an api (working) and generating a line plot with vue-chartjs.
However only the first two points are plotted. I must have my data structured in the wrong way but I don't know what it is expecting.
Here is my component:
import { Line } from "vue-chartjs";
export default {
extends: Line,
props: {
chartdata: {
type: Object,
default: null
}
},
mounted() {
this.renderChart(this.chartdata);
}
};
And in my App.vue file, I have this simple template:
<template>
<div id="app">
<div class="container">
<div class="Chart">
<h2>LineChart</h2>
<line-chart v-if="loaded" :chartdata="chartdata"></line-chart>
</div>
</div>
</div>
</template>
and this script:
<script>
import LineChart from './components/LineChart.js'
export default {
name: 'app',
components: { LineChart },
data:() => ({
loaded: false,
chartdata: null
}),
async mounted () {
this.loaded = false;
try {
let mydata = await fetch("http://myserver00/api/load/myserver02")
.then(stream => stream.json())
.then(mydata => {
let usercpu = [];
mydata.forEach(record => {
usercpu.push( record.cpu.user );
});
this.usercpu = usercpu;
});
} catch (e) {
console.error(e)
}
this.loaded = true;
this.chartdata = {
datasets: [
{label: 'CPU', data: this.usercpu}
]
};
}
}
</script>
As you may notice, I'm trying to system data from psutils to monitor servers. The original record from the api has several fields. This example just shows my attempt at CPU usage.
The browser tools show the data I expect, but apparently not what the chart expects. Here's a view of the data from the chrome vue devtools extension
Edit: to make sure the data is actually loaded, I added {{chartdata}} into my template and I see it all. Here is how it starts, the array goes on with all the data array. And the actual plot again shows only the first two data points.
{ "datasets": [ { "label": "CPU", "data": [ 2.7, 2.9, 3
Finally got it; I needed to re-read the doc for Chartjs. So here's the mounted function now. See that I had to put in x and y values for each point.
async mounted () {
this.loaded = false;
try {
let usercpu = [];
await fetch("http://server/api/load/server02")
.then(stream => stream.json())
.then(mydata => { mydata.forEach(record => {
usercpu.push( { y: record.cpu.user, x: record.date });});});
this.loaded = true;
this.chartdata = {
datasets: [ {
fill: false,
pointRadius: 0,
borderWidth: 2,
label: 'CPU',
data: usercpu
} ] };
} catch (e) {
console.error(e)
}
}
Also, in the data portion of the default function I had to add axes. I'm not exactly sure why, but even when the data was okay (above) I still couldn't see the plot. So when I added the axes, there everything was:
options: {
scales: {
xAxes: [{
type: 'time',
time: {
unit: "hour",
displayFormats: {
hour: "M/DD # hA"
},
tooltipFormat: "MMM. DD # hA"
},
scaleLabel: {
display: true,
labelString: "Date/Time"
},
ticks: { autoSkip: true, maxTicksLimit: 5},
position: 'bottom'
}],
yAxes: [{
ticks: {
suggestedMin: 0,
suggestedMax: 10
}
}]
}
And of course I had to include the options in the directive:
<template>
<div id="app">
<div class="container">
<div id="cpu">
<h2>Server02</h2>
<line-chart v-if="loaded" :chartdata="chartdata" :options="options"></line-chart>
</div>
</div>
</div>
</template>

How do I add dynamic data to apexcharts using vue.js?

I am trying to use dynamic data in my donut apexchart, but I don't know the correct way to do it.
I tried setting "test: 5" under data and then change the static number in series: [this.test, 4, 1]. Did not output anything, I am new to programming.
<script>
import VueApexCharts from 'vue-apexcharts'
export default {
name: 'Dashboard',
components: {
apexcharts: VueApexCharts
},
data () {
return {
test: 6,
series: [this.test, 5, 4],
chartOptions: {
plotOptions: {
pie: {
donut: {
labels: {
show: true,
name: {
fontSize: '24px'
},
value: {
fontSize: '34px',
color: '#fff'
}
}
}
}
},
tooltip: {
enabled: false
},
legend: {
show: false
},
fill: {
colors: ['#4b367c', '#2aa5ed', '#db2828']
},
dataLabels: {
enabled: false
},
labels: ['Utkast', 'Öppen', 'Förfallen'],
colors: ['#4b367c', '#2aa5ed', '#db2828']
}
}
},
mounted () {
this.$store.commit('setPageTitle', { title: 'Översikt' })
}
}
</script>
My goal is to reach in to firebase and use the data from there, but to start with I just wanted to test out how to add any data and failed here already.
You should not use one variable in another directly in data.
series: [this.test, 5, 4],
This will return null in this.test.
You can set series empty intially and set values later.
series:[]
And then populate series in some function.
Or else use computed() as follows:
computed: {
series() {
return this.test;
}
}
You can update the chart data dynamically like this.
this.chartOptions = {labels:['dynamic data here']}
this.series = ['dynamic data here']