Vuejs - Chartjs doesn't render my own options with api request - javascript

I have a problem when I want to fill my chart with my api.
My chart's extraOptions are set, but when I want to render my chart with it, it takes defaults options.
Here is my component:
import { Bar, mixins } from 'vue-chartjs';
export default {
name: 'bar-chart',
extends: Bar,
mixins: [mixins.reactiveProp],
props: {
extraOptions: Object,
chartData: Object,
},
data() {
return {
ctx: null
};
},
methods: {
},
mounted() {
this.renderChart(
this.chartData,
this.extraOptions
);
this.$watch('chartData', (newVal, oldVal) => {
if (!oldVal) {
console.log(this.extraOptions)
this.renderChart(
this.chartData,
this.extraOptions
);
}
}, { immediate: true });
}
};
And my overview with my Options and call api:
<div class="row">
<div class="col-lg-4">
<card>
<bar-chart :height="heightChart" :extraOptions="optionsBar" :chart-data="BarData"> </bar-chart >
</card>
</div>
</div>
</template>
<script>
import Loading from 'src/components/Dashboard/Layout/LoadingMainPanel.vue'
import LineChart from 'src/components/UIComponents/Charts/LineChart.vue'
import pieca from 'src/components/UIComponents/Charts/pieca.vue'
import Clock from './Clock.vue'
import BarChart from 'src/components/UIComponents/Charts/BarChart'
import axios from 'axios'
const WorldMap = () => ({
component: import('./../Maps/WorldMap.vue'),
loading: Loading,
delay: 200
})
export default {
components: {
LineChart,
pieca,
Clock,
BarChart
},
/**
* Chart data used to render stats, charts. Should be replaced with server data
*/
data () {
return {
optionsLine: {
responsive: true,
maintainAspectRatio: false,
title: {
display: true,
text: 'CA Mensuel/12 mois',
fontSize: 17,
fontFamily: "'Montserrat', 'Helvetica Neue', Arial, sans-serif",
fontStyle: 'normal',
fontColor: 'black',
}
},
optionsBar: {
maintainAspectRatio: false,
legend: {
display: false,
labels: {
fontColor: '#ced4da'
}
},
title: {
display: true,
text: 'Cmd/Transporteur',
fontSize: 17,
fontFamily: "'Montserrat', 'Helvetica Neue', Arial, sans-serif",
fontStyle: 'normal',
fontColor: 'black',
},
responsive: true,
tooltips: {
backgroundColor: '#f5f5f5',
titleFontColor: '#333',
bodyFontColor: '#666',
bodySpacing: 4,
xPadding: 12,
mode: "nearest",
intersect: 0,
position: "nearest"
},
legend: {
display:true,
position: 'bottom'
},
scales: {
yAxes: [{
stacked: true,
gridLines: {
drawBorder: false,
color: 'rgba(29,140,248,0.1)',
zeroLineColor: "transparent",
},
ticks: {
suggestedMin: 60,
suggestedMax: 120,
padding: 20,
fontFamily: "'Poppins',sans-serif",
fontColor: "#ced4da"
}
}],
xAxes: [{
stacked: true,
gridLines: {
drawBorder: false,
color: 'rgba(29,140,248,0.1)',
zeroLineColor: "transparent",
},
ticks: {
padding: 20,
fontFamily: "'Poppins',sans-serif",
fontColor: "#ced4da"
}
}]
}
},
heightChart: 255,
BarData: {
},
And my api request:
axios
.get('api_url')
.then(response => (globalthis.BarData = response.data.transporteur_jour
))
I think my chart is rendering with my extraOptions and when it's fill with api data, it takes the defaults options. When I don't call my api and fill the labels directly in my overview, it works.
How can I do to keep my extraOptions ?
Thanks

i had the same problem with chart data in nuxt.js
add a key to your component and when you get the api response change the value of the key . Vue will re-render the component after this change
my component :
<LineChartComponent :chart-data="datacollection" :height="400" :key="datacollection.key"></LineChartComponent>

Related

Vue-ChartJS keeps throwing [Vue warn]: Error in mounted hook: "RangeError: Maximum call stack size exceeded" keeps showing

Every time I include a chart in a page I keep getting this in the console: [Vue warn]: Error in mounted hook: "RangeError: Maximum call stack size exceeded".
The chart loads and acts as expected but I keep getting this warning.
I am using vue-chartjs v4.0.7 with chart.js v3.7.1 in Vue 2.6.14.
The usage of the component is basic. I include it in another component like this:
<StatisticsGraph :statisticsGraph="statisticsGraph" style="max-height:490px; width:100%;"/>
And then the component looks like this:
<template>
<LineChart :chart-data="chartData" :chart-options="chartOptions"/>
</template>
<script>
import 'chart.js/auto';
import { Line } from 'vue-chartjs/legacy';
export default{
components: {LineChart: Line},
props: {
statisticsGraph: Object
},
data: function(){
var labels = [
'Monday','Monday-end','Friday','Friday-end'];
return {
chartData: {
labels: labels,
datasets: [
{
type: 'line',
steppedLine: true,
data: this.statisticsGraph.last_week,
borderColor: '#d0d7e1',
pointRadius: 0,
borderWidth: 2,
fill: false,
},
{
type:'line',
steppedLine: true,
data: this.statisticsGraph.this_week,
borderColor: '#77c0b4',
backgroundColor: '#77c0b4',
pointRadius: 0,
borderWidth: 2,
fill: false,
},
]
},
chartOptions: {
plugins: {
legend: {
display: false,
labels: {
boxWidth: 20,
}
},
},
scales: {
x: {
grid: {
display: false,
},
ticks: {
padding: 10,
fontColor: '#95AAC9',
fontSize: 13,
autoSkip: false,
maxRotation: 0,
callback: (value) => {return (labels[value] === 'Monday' || labels[value] === 'Friday') ? labels[value] : ' '}
},
},
y: {
grid: {
drawBorder: false,
},
ticks: {
fontColor: '#95AAC9',
fontSize: 13,
}
}
},
responsive: true,
maintainAspectRatio: false
}
}
}
}
</script>
Any idea what might cause this?

Chart JS tooltip labels spaced as spaceBetween

I have a stacked bar chart where the tooltip shows Label: $value & I would like this to be set as space-between so Label is aligned to the left & $value is aligned to the right, allowing all the numerical values to align. For example:
Label 1: $10,000
Label 2: $50,000
Label 3: $100,000
Here is the calculator. Just press the compound button to show the chart.
https://youthful-euclid-784d05.netlify.app
ChartJS options:
// Configuration options go here
options: {
responsive: true,
maintainAspectRatio: true,
legend: {
display: true,
position: "bottom"
},
scales: {
xAxes: [{
ticks: {
fontSize: 16,
fontFamily: "Roboto Condensed"
},
gridLines: {
display: false,
},
scaleLabel: {
display: true,
labelString: 'Year',
fontSize: 16,
fontFamily: "Roboto Condensed"
},
stacked: true,
}],
yAxes: [{
stacked: true,
ticks: {
maxTicksLimit: 5,
beginAtZero: true,
fontSize: 12,
fontFamily: "Roboto Condensed",
callback: function (value, index, values) {
if (parseInt(value) >= 1000) {
return (
numeral(value).format("$0a")
// "$" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
);
} else {
// return "$" + value;
}
},
},
}, ],
},
legend: {
display: true,
labels : {
fontSize: 14,
fontFamily: "Roboto Condensed",
},
},
chart: {
},
tooltips: {
// displayColors: false,
yAlign: "bottom",
callbacks: {
title: function (tooltip, data) {
return `After ${tooltip[0].label} Years`;
},
label: function(tooltipItems, data) {
return ` ${data.datasets[tooltipItems.datasetIndex].label}: ${formatCurrency(tooltipItems.value)}`;
},
},
// bodyAlign: "center",
titleFontSize: 15,
titleMarginBottom: 10,
bodySpacing: 10,
bodyFontSize: 12,
mode: "x",
xPadding: 10,
yPadding: 10,
// bodySpacing: "5"
},
}

Angular Chart.JS Only One Canvas Rendering

I created a bar chart component and this is working fine. However I run into problems when trying to display multiple charts with the same component. I'm generating "tiles" dynamically through an ngFor and inside each tile there's a component. The issue is that only the first tile is generating a chart and the rest of the tiles are not. Apologies in advance if I did not provide enough information just let me know and I'll provide more.
ngFor
<div *ngFor="let productLevel of productLevels" class="col-xl-2 col-lg-3 col-md-3 col-sm-4 col-6" align="center">
<app-health-tile [routerLink]="['/details/',group,productLevel.plId]" [title]="productLevel.plId" [up]="productLevel.up" [warning]="productLevel.warning" [down]="productLevel.down"></app-health-tile>
</div>
health-tile.component.ts
<div id="tile" [ngClass]="{'error': error, 'warning': issue, 'healthy': healthy}" align="left">
<div>{{title}}</div>
<app-barchart></app-barchart>
<div id="counter">
{{up}} <i class="fa fa-long-arrow-up" aria-hidden="true"></i>
{{warning}} <i class="fa fa-exclamation" aria-hidden="true"></i>
{{down}} <i class="fa fa-long-arrow-down" aria-hidden="true"></i>
</div>
</div>
barchart.component.ts
import { Component, OnInit } from '#angular/core';
import { Chart } from 'chart.js';
#Component({
selector: 'app-barchart',
templateUrl: './barchart.component.html',
styleUrls: ['./barchart.component.css']
})
export class BarchartComponent implements OnInit {
barChart = [];
constructor() { }
ngOnInit(): void {
this.barChart = new Chart('canvas', {
type: 'bar',
data: {
backgroundColor: "#FFFFFF",
labels: ['4H', '4L', 'Close'],
datasets: [{
label: '# of Inc.',
data: [2,3,1],
borderColor: '#FFFFFF',
backgroundColor: "#FFFFFF",
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
display: true,
gridLines: {
// display: false,
drawOnChartArea: false,
zeroLineColor: '#FFFFFF',
color: '#FFFFFF',
fontStyle: "bold",
},
ticks: {
fontColor: '#FFFFFF',
fontFamily: 'Lato',
fontStyle: "bold",
precision:0
},
}],
yAxes: [{
display: true,
gridLines: {
drawOnChartArea: false,
zeroLineColor: '#FFFFFF',
color: '#FFFFFF',
fontStyle: "bold",
},
ticks: {
fontColor: '#FFFFFF',
fontFamily: 'Lato',
fontStyle: "bold",
precision:0
},
}],
}
}
});
}
}
Problem was with your canvas id, you should pass dynamic ids to your chart.
For example:
You have to pass dynamic ids from your component to the canvas.
and you have instantiate your Chart in ngAfterViewInit ie. after View gets initialized.
Your chart template should be like this:
<div class="chart-container">
<canvas [id]="chartId" >{{ barChart }}</canvas>
</div>
barchart test
and in your component it should be like this:
export class BarchartComponent implements OnInit {
#Input() chartId:string;
barChart = [];
constructor(
) { }
ngOnInit(): void {
setTimeout(() => {
this.barChart = new Chart(this.chartId, {
type: 'bar',
data: {
backgroundColor: "#000000",
labels: ['4H', '4L', 'Close'],
datasets: [{
label: '# of Inc.',
data: [2,3,1],
borderColor: '#000000',
backgroundColor: "#000000",
}]
},
options: {
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
display: true,
gridLines: {
// display: false,
drawOnChartArea: false,
zeroLineColor: '#000000',
color: '#000000',
fontStyle: "bold",
},
ticks: {
fontColor: '#000000',
fontFamily: 'Lato',
fontStyle: "bold",
precision:0
},
}],
yAxes: [{
display: true,
gridLines: {
drawOnChartArea: false,
zeroLineColor: '#000000',
color: '#000000',
fontStyle: "bold",
},
ticks: {
fontColor: '#000000',
fontFamily: 'Lato',
fontStyle: "bold",
precision:0
},
}],
}
}
}, 100);
})
}
}
Here is the working demo for the same.
demo

How to add gradient background to Line Chart [vue-chart.js]

how can I add a gradient backgroundColor to a line chart, I pass the data as props.
this is my LineChart.vue component:
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
data: () => ({
gradient: null,
options: {
layout: {
padding: {
bottom: -20,
left: -20,
}
},
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
yAxes: [{
ticks: {
beginAtZero: true,
min: 0,
display: false,
},
gridLines: {
drawBorder: false,
showBorder: false,
display: false,
},
}],
xAxes: [{
gridLines: {
drawBorder: false,
showBorder: false,
display: false,
},
ticks: {
display: false
}
}]
}
}
}),
mounted () {
// this.chartData is created in the mixin.
// If you want to pass options please create a local options object.
this.renderChart(this.chartData, this.options)
}
}
and this is the chartdata initialization in Home.vue:
this.chartdata3 = {
labels: ['bla', 'bla', 'bla', 'bla'],
datasets: [
{
backgroundColor: "rgba(42, 115, 237, 0.9)",
data: ['200', '400', '100', '700'],
}
]
};
How can I have a gradient instead of solid color in the background of the line chart?
You should be able to add ref="chart" to your canvas. After that you can declare the new variable that will store the background color.
Like this:
var gradientFill = this.$refs.chart.createLinearGradient(500, 0, 100, 0);
gradientFill.addColorStop(0, "rgba(128, 182, 244, 0.6)");
gradientFill.addColorStop(1, "rgba(244, 144, 128, 0.6)");
Then you should be able to use backgroundColor: gradientFill in your chart options.
Please put this code in created or mounted methods in Vue lifecycle as needed to make sure it renders properly when component displays.
That should be it.
Yo can try and play with it here: https://codepen.io/plavookac/pen/RKjNEV
I hope this helps.
Let me know if you have any questions.

Angular: want to display names inside the bars of a chart

Im using chartjs to display some data. Im trying to dynamically add data to datasets array but its not working.
Using additional plugins :-- Legend() Plugin
this.chart = new Charts ('LineChart',
{
type: 'bar',
data: {
labels: this.graphdates,
// data : this.graphname,
datasets: [
{
label: 'prizemoney',
data: this.graphprize,
backgroundColor: "#0000FF",
value : this.grpdata,
},
{
label: 'Bid Amount',
data: this.graphbid,
backgroundColor: "#FF1493",
},
],
plugins: [
Chartist.plugins.legend()
]
},
options: {
animation: {
duration: 10,
},
plugins: [ legend() ],
legend: {
labels: {
// This more specific font property overrides the global property
fontColor: 'black',
series : this.graphname,
}
},
responsive: true,
maintainAspectRatio: false,
tooltips: {
mode: 'label',
backgroundColor: '#FFF',
titleFontSize: 16,
titleFontColor: '#0066ff',
bodyFontColor: '#000',
bodyFontSize: 14,
displayColors: false
},
scales: {
xAxes: [{
stacked: true,
barPercentage: 0.6,
gridLines: { display: false },
ticks: {
fontSize: 15
},
scaleLabel: {
display: true,
labelString: 'Auction Date',
fontSize: 25,
fontStyle: "bold",
},
}],
yAxes: [{
stacked: true,
ticks: {
fontSize: 15
},
scaleLabel: {
display: true,
labelString: 'Amount',
fontSize: 25,
fontStyle: "bold",
}
}],
},
legend: {display: true}
}
});
Want to display the some data in the bars i.e. on Y-axis.

Categories