I am buiding a website with laravel and using the vuejs to manage the front-end. I want to display several charts through vue-chartjs but the vue-chartjs is not showing the graph even though the data is successfully passed. I have been following their website guide but the graph never displays.
My Vue Component
<teplate>
<div>
...
<line-chart :chart-data="datacollection"></line-chart>
<button #click="fillData()">Randomize</button>
</div>
</template>
<script>
import Table from '../equipments/table.vue'
import LineChart from '../equipments/LineChart.js'
import DropDownList from '../equipments/dropdownlist.vue'
export default {
data () {
return {
datacollection: null
}
},
components: {
LineChart,
Table,
DropDownList
},
mounted () {
this.fillData()
},
methods: {
fillData () {
this.datacollection = {
labels: ['weqw','wewq'],
datasets: [
{
label: 'Data One',
backgroundColor: '#f87979',
data: [this.getRandomInt(), this.getRandomInt()]
},
{
label: 'Data One',
backgroundColor: '#f87979',
data: [this.getRandomInt(), this.getRandomInt()]
}
]
}
},
getRandomInt () {
return Math.floor(Math.random() * (50 - 5 + 1)) + 5
}
}
}
</script>
<style>
.small {
max-width: 600px;
margin: 150px auto;
}
</style>
my Chart.js
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
props: ['options'],
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)
}
}
Hope could receive some hints here, thanks in advance
Vue-chartjs only works with v2 of chart.js. So you will need to downgrade chart.js to version 2.9.4 if you want to use it.
npm i chart.js#2.9.4
Related
Within vue3 is it possible to bind a value from the vuex store to a component style? for example, i have a color saved within the store as backgroundColor and would like to do something like below:
Store:
store = {
state: {
branding: {
color: '#f00'
}
}
}
component script
export default {
name: 'component',
components: {
Header,
Footer
},
branding() {
return this.$store.state.branding.color;
},
}
component style
.page{
background-color: v-bind(branding.colour);
}
i have seen an example of this working:
export default {
name: 'component',
components: {
Header,
Footer
},
data(){
return {
color: '#f00'
}
},
}
.page{
background-color: v-bind(colour);
}
but i need to grab the data from the store. im pretty new to vue but not too sure on how to resolve this.
UPDATE 6 April 2022
Apparently I was wrong and in Vue 3 it is possible to use v-bind inside CSS as shown in the documentation. So it should be possible to use Vuex getter or local computed property.
You can not access JavaScript variables from CSS. You should either set inline style to your HTML tag(s) or define the color as CSS variable and then access it from other CSS rules.
<template>
<div :style="{backgroundColor: brandingColor}">test</div>
</template>
<script>
export default
{
computed:
{
brandingColor()
{
return this.$store.state.branding.color;
}
}
}
</script>
OR
// main.js
new Vue({
created()
{
const style = document.documentElement.style;
const theme = this.$store.state.branding;
for (const key in theme)
{
style.setProperty('--branding-' + key, theme[key]);
}
}
});
MyComponent.vue:
<template>
<div class="page">text</div>
</template>
<style>
.page
{
background-color: var(--branding-color);
}
</style>
I'm using Highcharts stock in Vue, what I want to implement is when I hover one stock point, the tooltip shows up, and at the same time, at other places may be top of the stock chart, as same as data in tooltip in other styles. My way is to export data in the tooltip formatter function, but in the formatter function this doesn't refer to Vue instance. I wonder if there any way I can access hovering tooltip data, or if there any other way can realize the effect.
the effect i want to realize
<template>
<div>
<div class="outerTooltip">open: xxx</div>
<highcharts :constructor-type="'stockChart'" :options="stockOptions"></highcharts>
</div>
</template>
<script>
import { Chart } from "highcharts-vue";
import Highcharts from "highcharts";
import stockInit from "highcharts/modules/stock";
import { data } from "./stockData";
stockInit(Highcharts);
export default {
name: "StockVue",
computed: {
stockOptions() {
return {
...,
tooltip: {
shared: true,
formatter(){
console.log(this)
// how can i export data in this to Vue, so i can show it in outerTooltip dynamically
retuen `
open: ${this.points[0].point.open}
`
}
}
}
}
}
}
codesandbox example
I think that you only need to assign the reference of the Vue instance to a variable and then use it in formatter function. Remember also to add a reference to the computed property.
Demo: https://codesandbox.io/s/highcharts-vue-test-forked-c7pvw?file=/src/components/StockVue.vue
Assign the reference of the Vue instance to a variable that worked for me.
export default {
name: "StockVue",
method: {
exportTooltipData(data){
console.log(data)
}
},
computed: {
stockOptions() {
const exportFn = this.exportTooltipData;
return {
...,
tooltip: {
shared: true,
formatter(){
exportFn(this);
retuen `
open: ${this.points[0].point.open}
`
}
}
}
}
}
}
I have a graph in my application, which was created with Chart.js library. My graph.js file looks like this:
import { Line, mixins } from 'vue-chartjs';
const { reactiveProp } = mixins;
export default {
extends: Line,
mixins: [reactiveProp],
data() {
return {
options: {
maintainAspectRatio: false,
responsive: true,
legend: {
display: true,
position: 'bottom',
},
scales: {
yAxes: [
{
ticks: {
suggestedMin: 0,
callback(tick) {
return `${tick}%`;
},
},
},
],
},
tooltips: {
callbacks: {
label(tooltipItem, data) {
const dataset = data.datasets[tooltipItem.datasetIndex];
const currentValue = dataset.data[tooltipItem.index];
return ` ${dataset.label}: ${currentValue}%`;
},
},
},
},
};
},
mounted() {
this.renderChart(this.chartData, this.options);
},
};
And the component responsible for rendering it (i've cut some irreleveant details):
<template>
<div
class="container">
<b>
...
</b>
<div
class="graph">
<graph
:styles="graphStyle"
:chart-data=graphData">
</graph>
</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
import Graph from './graph';
import {
...
} from '../../constants';
export default {
name: '...',
components: {
Graph,
},
data() {
return {
...
};
},
watch: {
...
},
methods: {
...
},
computed: {
...
},
};
</script>
I would like to export it to svg, and then post it to my api. I need to serialize it into a string and then send with post method, in json body. Do i have to use some another external library? How can i serialize it to svg? Thanks for any answers.
If png is acceptable for you, there might be a way to do it. Keep in mind that I haven't tested this, but it should work by the looks of it.
Looking at the documentation of vue-chartjs, here it says that you can access the chartjs object with:
this.$data._chart
From there, you should be able to use its method for saving the chart as a png - toBase64Image():
this.$data._chart.toBase64Image()
I'm trying to reload the data on a bar chart from chart.js, but im not able to.
This is the chart:
<script>
import { Bar } from 'vue-chartjs'
export default {
extends: Bar,
props: ["chartdata"],
data: () => ({
options: {
responsive: true,
maintainAspectRatio: false
}
}),
computed: {
chartData: function() {
return this.data;
}
},
watch: {
data: function() {
this._chart.destroy();
this.renderChart(this.data, this.options);
}
},
mounted () {
this.renderChart(this.chartdata, this.options)
}
}
</script>
This is how I implement it:
<chart
:chartdata="chartdata"
:options="options"/>
After getting the data from the api and form the chartdata I try to trigger the watch by updating the container data that I'm sending like this:
const cd = {
labels: labels,
datasets: [{
label: '# of Votes',
data: data
}]}
this.chartdata = cd
}
But It's not working and I don't know why.
Neither familiar with the library or vue.js in general, but the documentation says the following about updating the chart...
Chart.js does not provide a live update if you change the datasets.
However, vue-chartjs provides two mixins to achieve this.
reactiveProp reactiveData Both mixins do actually achieve the same.
Most of the time you will use reactiveProp. It extends the logic of
your chart component and automatically creates a prop named chartData
and adds a vue watch on this prop. On data change, it will either call
update() if only the data inside the datasets has changed or
renderChart() if new datasets were added.
You're not using the mentioned props in the documentation. You can read more it on the official documentation
If you are using vue-chartjs, the library has its own way to handle reactive data in charts:
// ChartBar.js
import { Bar, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Bar,
mixins: [reactiveProp],
props: ['options'], // passed from the parent
mounted () {
// this.chartData is created in the mixin (pass it as any prop with :chart-data="data").
this.renderChart(this.chartData, this.options)
}
}
Now use the component
<chart
:chart-data="chartdata"
:options="options"
/>
You can read more about it here: https://vue-chartjs.org/guide/#updating-charts,
there are some caveats
I'm trying to render a simple pie chart in a react component, using the Chart.js library.
I've managed to render a Line chart, but for some reason my Pie chart is just rendering an empty canvas. Is it a problem with the chartData not being valid? I'm not getting any kind of error.
import React, { Component, PropTypes } from 'react';
import * as axios from 'axios';
import s from './Test.css';
import withStyles from 'isomorphic-style-loader/lib/withStyles';
import cx from 'classnames';
var PieChart = require("react-chartjs").Pie;
class Test extends Component {
constructor(props) {
super(props);
this.chartData = {
datasets: [{
data: [100, 200, 300],
backgroundColor: ["#FF6384", "#36A2EB", "FFCE56"]
}]
};
this.chartOptions = {
scale: {
reverse: true,
ticks: {
beginAtZero: true
}
}
};
};
render() {
return(<div className={s.graphic}><PieChart data={this.chartData} options={this.chartOptions} width="600" height="250" /></div>);
}
}
export default withStyles(s)(Test);
Apologies for the first (non) answer. I've actually got somewhere:
The problem was my CSS.
canvas {
width: 100% !important;
height: auto !important;
}
For some reason still not known to me forcing the pie chart sizes causes it not to render. Removing the css solved the rendering problem.