Reload chart on api call - javascript

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

Related

Vue-Chartjs not rendering graph

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

How to access Highcharts stock tooltip data in Vue?

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}
`
}
}
}
}
}
}

Error while parsing a string that I receive from backend

I'm currently using ChartJS for displaying a chart and in that, I'm receiving all the data from the backend. The problem is that the options properties like chart header, yaxis ticks, etc aren't being added to the chart.
Here is my Universal Chart component:
class UniversalChart extends Component {
constructor(props) {
super(props);
}
chartRef = React.createRef();
componentDidMount() {
const myChartRef = this.chartRef.current.getContext("2d");
console.log('options Data inside Uni Chart',this.props.options);
new Chart(myChartRef, {
type: this.props.type,
data: { labels: this.props.labels, datasets: this.props.data },
options: this.props.options
})
}
render() {
return <canvas ref={this.chartRef} height={this.props.height} />
}
}
Here is data that I receive from options inside of my Universal Chart component: {"responsive":true,"title":{"display":true,"text":"Sales trend"},"legend":{"position":"bottom"},"scales":{"yAxes":[{"ticks":{"beginAtZero":true,"stepSize":20}}]}}
Here is a screenshot of the console log:
Also, here is the screenshot of the chartOptions data that I receive in the ChartBox component and which I pass it down to Universal chart.
I pass down the data to Universal Chart component from the parent ChartBox component like this:
<UniversalChart
type={props.data.chart_data_config.chartType}
data={props.data.datasets}
labels ={props.data.labels}
options={props.data.chart_data_config.chartOptions}
height={props.data.chart_data_config.height}
/>
I also tried this inside my Universal Chart comp:
options: JSON.parse(this.props.options)
But that's giving me a cross-origin error: Uncaught Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development.
Please let me know the solution to the problem. I want the UniversalChart comp to read the options json that I'm passing to show the chart header and utilize the other properties.

How to properly split a Vuejs component

So, I've got a huge Vue file which do more than 1500 lines CSS excluded.
This file is a wrapper for a lot of other components but mostly can't be breaked into smaller components.
The things is I still got some logics like groups of methods which could be extracted. However it has impact on some data or watched properties.
Is it possible to export differents parts of my file and use them as a more "global import".
Something which would be like :
// components/component.logicX.vue/js?
export default {
data() {
return {
....
}
},
methods: {
aFewMethods(){ this.data = "something" },
...
},
watch: {
...
}
}
// component/component.vue
import logicX from '.component.logicX.vue'
export default {
components: {
logicX
},
data() {
data: '' //this data is modified from a logicX component method.
}
}

How I Can Change The Another Component Data on VueJS

I have a classic Vue Component like this
Vue.component('bar', {
template: `<div class="bar"></div>`,
data () {
return {
blocks: [
]
}
}
});
And also i have Vue Instance like this.
new Vue ({
el: '#app',
data: {
value: 1
},
methods: {
add: function() {
// here to do
}
}
});
When add function work, i have to add to data component blocks value. I can't use Vuex and what is this other solutions?
Since this is a parent -> child communication, you can very simply use props:
Store blocks on the parent component.
Pass blocks as a prop to bar component.
Do any additional processing using computed properties.
Display data using child's template.
Here's some guiding:
Define your component with props:
Vue.component('bar', {
template: `<div class="bar">{{blocks.length}}</div>`,
props: ['blocks']
});
Define blocks on the parent (in your example, the main vue component):
new Vue ({
el: '#app',
data: {
blocks: []
},
methods: {
add: function() {
// do something with blocks
}
}
});
Pass data down to the component:
<bar :blocks="blocks"></bar>
You can use the way which called “Event bus”
https://alligator.io/vuejs/global-event-bus/
Or you can create your own state management
https://v2.vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch
But i highly recommend you too use vuex, since it will become hard to manage events and state when the project grows

Categories

Resources