0👍
Finally, I got the answer Hoorah!
I am sharing, how I did it even you can do the same in order to visualize chart with your API data.
<template>
<div class="chart-container" style="position: relative; height: 25vh; width:100%;">
<canvas id="DisplayChart" ></canvas>
</div>
</template>
<script>
import moment from 'moment'
export default {
name: 'Chart_from_API',
data () {
return {
myChart: []
}
},
async mounted () {
await this.$http.get('https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs') //Your API has to be given here
.then((response) => {
const result = response.data
const ctx = document.getElementById('DisplayChart').getContext('2d')
const Chart_data = []
for (let i = 0; i < result.date.length; i++) {
Chart_data.push({
x_axis: moment(result.date[i], 'X').toDate(), //To Convert Unix Timestamp into Date
y_axis: result.challenge[i]
})
}
// eslint-disable-next-line init-declarations,prefer-const
let myChart
if (myChart !== undefined) {
myChart.destroy()
}
// eslint-disable-next-line no-undef
myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
label: 'Chart_from_API',
data: Chart_data,
borderColor: '#EA5455',
lineTension: 0
}
]
},
options: {
lineTension: 0,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [
{
scaleLabel: {
display: false
},
ticks: {
beginAtZero: true,
// eslint-disable-next-line no-unused-vars
callback (value) {
return `${value }k` // y-axis value will append k to it
}
}
}
],
xAxes: [
{
type: 'time',
time: {
unit: 'month'
},
scaleLabel: {
display: true,
labelString: ''
}
}
]
}
}
})
})
.catch((error) => {
console.log(error)
})
}
}
</script>
2👍
have you tried like this one?
solution 1
Add async/await
so it will wait until the data get populated to data
and challege
.
async mounted () {
let result = await axios.get('https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs')
this.date = result.data.date
this.challenge = result.data.challenge
// eslint-disable-next-line no-unused-vars
const data = this.date.map((date, index) => ({
x: new Date(date * 1000),
y: this.challenge[index]
}))
const ctx = document.getElementById('mychart').getContext('2d')
// eslint-disable-next-line no-undef,no-unused-vars
const Chart_2 = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
data,
label: 'Chart from API ',
borderColor: '#7367F0'
}
]
},
options: {
scales: {
xAxes: [
{
type: 'time',
time: {
unit: 'month',
displayFormats: {
month: 'MMM YYYY'
}
}
}
],
yAxes: [
{
ticks: {
// eslint-disable-next-line no-unused-vars
callback (value, index, values) {
return `${value }%`
}
}
}
]
}
}
})
}
or in another way, you can fetch the data from API in other component and send date
and challege
as props to this component.
solution 2
I assume you have chart component chart.vue
chart.vue
<template>
<canvas id="mychart" width="550" height="300"></canvas>
</template>
<script>
export default {
name: 'Chart',
props: ['date', 'challenge],
data: () => ({
}),
mounted () {
// eslint-disable-next-line no-unused-vars
const data = this.date.map((date, index) => ({
x: new Date(date * 1000),
y: this.challenge[index]
}))
const ctx = document.getElementById('mychart').getContext('2d')
// eslint-disable-next-line no-undef,no-unused-vars
const Chart_2 = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
data,
label: 'Chart from API ',
borderColor: '#7367F0'
}
]
},
options: {
scales: {
xAxes: [
{
type: 'time',
time: {
unit: 'month',
displayFormats: {
month: 'MMM YYYY'
}
}
}
],
yAxes: [
{
ticks: {
// eslint-disable-next-line no-unused-vars
callback (value, index, values) {
return `${value }%`
}
}
}
]
}
}
})
}
}
</script>
and in other component, import your chart.vue
<template>
<div>
<Chart v-if="!isLoading" :date="date" :challenge="challenge" />
</div>
</template>
<script type="text/javascript">
import Chart from 'PATH TO chart.vue'
export default {
components: {
Chart
},
data () => ({
date: [],
challenge: [],
isLoading: false
}),
methods: {
async getData () {
this.isLoading = true
let result = await axios.get(API URL)
this.date = result.data.date
this.challenge = result.data.challenge
this.isLoading = false
}
},
mounted () {
this.getData()
}
}
</script>
In chart.vue, delete date
and challege
from data
because you will have props
, for the best practice props
and data
cannot have same property name.
In other component where chart.vue get imported, just fetch the data as usual.
Things I did when I was using chartjs for my project, I always add v-if
in , it will let the axios fetch the data first and then re-mount the chart component. Because I guess chartjs is not reactive on vuejs data changes, so will need to update the data first then re-mount again.
0👍
You can use the vue-chartjs
which is a wrapper for Chart.js in Vue.
Install it over the npm
package manager.
npm install vue-chartjs chart.js
According to the documentation, there is a common problem when accessing the data from an asynchronous API endpoint:
The problem with this approach is that Chart.js tries to render your chart and access the chart data synchronously, so your chart mounts before the API data arrives.
To prevent this, a simple v-if
is the best solution. The following Vue component utilizes a boolean variable to stop the chart mounting before the data arrives.
<template>
<div>
<h1>Stock Data</h1>
<!-- The v-if is used to conditionally render a block -->
<Bar id="my-chart-id" v-if="loaded" :options="chartOptions" :data="chartData" :width="600" />
</div>
</template>
<script>
import { Bar } from 'vue-chartjs'
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale } from 'chart.js'
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
export default {
name: 'BarChart',
components: { Bar },
data: () => ({
// Prevents chart to mount before the API data arrives
loaded: false,
chartData: {
labels: [],
datasets: [
{
label: 'My Label',
data: [],
backgroundColor: 'rgba(54, 162, 235, 0.2)'
}
]
},
chartOptions: {
responsive: true
}
}),
async mounted() {
const apiUrl = 'http://localhost:8000/data'
// Make an HTTP request to fetch the data from the API endpoint
await fetch(apiUrl)
.then((response) => response.json())
.then((data) => {
// Extract data from the API response and update the chartData
this.chartData.labels = data.map((stock) => stock.date)
this.chartData.datasets[0].data = data.map((stock) => stock.value)
// Allow the chart to display the data from the API endpoint
this.loaded = true
})
.catch((error) => {
console.error('Error fetching data:', error)
})
}
}
</script>
The key is to render the bar chart only if the data is arrived successfully. It is achieved by setting the loaded
variable to true. Note that, you need to reload the page whenever new data is arrived.