Nivo bar chart calling label function hundreds of times - javascript

I'm using Nivo bar to represent a user's progress on a budget. I've normalized the data by dividing the category balance by the category goal. Example data.
[{
"category": "Gas",
"budget": 0.24,
"over_budget": 0.0
},
{
"category": "Groceries",
"budget": 1.0,
"over_budget": 0.26
}]
I don't want these values to be used as the label on the chart. I plan to use the actual balance value as the label. I have an endpoint that will return the balance for a category and have attempted the following to use that value:
<ResponsiveBar
...
label={d => this.getDollarAmount(d.value)}
...
>
With the function POC as:
getDollarAmount(value) {
console.log("hitting getDollarAmount")
return 1
};
The log message gets logged 500+ times. My expectation would be that the function would only be hit once for each bar in the chart.
I'm still learning react so this could be something obvious. Thanks in advance!
EDIT - Here's the entire BarChart component:
import axios from 'axios';
import React, { Component } from "react";
import { ResponsiveBar } from '#nivo/bar'
// Nivo theming
const theme = {
axis: {
ticks: {
line: {
stroke: "#e9ecee",
strokeWidth: 40
},
text: {
// fill: "#919eab",
fill: "black",
fontFamily: "BlinkMacSystemFont",
fontSize: 16
}
}
},
grid: {
line: {
stroke: "#e9ecee",
strokeWidth: 5
}
},
legends: {
text: {
fontFamily: "BlinkMacSystemFont"
}
}
};
let budgetStatusAPI = 'http://127.0.0.1:8000/api/budget_status/?auth_user=1&month=2020-02-01';
class BarChart extends Component {
constructor(props) {
super(props);
this.state = {
data: [],
}
this.getDollarAmount = this.getDollarAmount.bind(this);
}
componentDidMount() {
console.log("component did mount")
axios.get(budgetStatusAPI).then(response => {
this.setState({
data: response.data
}, function () {
console.log(this.state.data);
})
});
}
componentDidUpdate() {
console.log("component did update")
}
getDollarAmount(value) {
console.log("hitting getDollarAmount")
console.log(value)
return 1
};
render() {
const hard_data = [
{
"category": "Groceries",
"budget_status": 1.0,
"over_budget": .26,
},
{
"category": "Gas",
"budget_status": .24,
"over_budget": 0.0,
}]
return(
<ResponsiveBar
maxValue={1.5}
markers={[
{
axis: 'x',
value: 1,
lineStyle: { stroke: 'rgba(0, 0, 0, .35)', strokeWidth: 2 },
legend: 'Goal',
legendOrientation: 'horizontal',
legendPosition: 'top'
},
]}
enableGridX={false}
gridXValues={[1]}
enableGridY={false}
data={this.state.data}
// data={hard_data}
keys={['budget_status', 'over_budget']}
indexBy="category"
margin={{ top: 25, right: 130, bottom: 50, left: 125 }}
padding={0.3}
layout="horizontal"
colors={{ scheme: 'set2' }}
theme={theme}
defs={[
{
id: 'dots',
type: 'patternDots',
background: 'inherit',
color: '#38bcb2',
size: 4,
padding: 1,
stagger: true
},
{
id: 'lines',
type: 'patternLines',
background: 'inherit',
color: '#eed312',
rotation: -45,
lineWidth: 6,
spacing: 10
}
]}
borderColor={{ from: 'color', modifiers: [ [ 'darker', 1.6 ] ] }}
axisBottom={null}
label={d => this.getDollarAmount(d.value)}
isInteractive={false}
animate={true}
motionStiffness={90}
motionDamping={15}
/>
)
}
}
export default BarChart;
Reproduced here: https://codesandbox.io/s/nivo-bar-label-issue-k4qek

The multiple calling is happening because the bar chart is calling label function for each animation tick/frame render. If we setup a counter, we'll see with animate prop set to true it will render from 450+ to 550+ times, but if we set the prop animate to false, we'll it renders 6 times which is exactly how many price values are > 0.0.
If you want to avoid all these renders, you'll have to disable animation using animate={false} prop like this:
getDollarAmount(value) {
// Remove every console.log inside this function
return `$${value}`
}
render() {
return (
<ResponsiveBar
animate={false}
label={d => this.getDollarAmount(d.value)}
...
);
}
You can check it running to your cloned CodeSandbox. I have set animate to false and the counter log inside getDollarAmount is calling 6 times. Try to change animate to true and you'll see the 500+- renders.
Also, you don't have to create a function for each label call, you can just pass the getDollarAmount function and let it handle the whole d parameter like this:
getDollarAmount(d) {
// Remove every console.log inside this function
return `$${d.value}`
}
render() {
return (
<ResponsiveBar
animate={false}
label={this.getDollarAmount}
...
);
}

Related

How to add onclick event on chart label in react-chartjs-2?

I want open a dialog when clicking on chart js label. This is the dataset code:-
const data = {
datasets: [
{
label: 'Reviews',
backgroundColor: theme.palette.primary.main,
data: dataProp.reviews,
barThickness: 12,
maxBarThickness: 10,
barPercentage: 0.5,
categoryPercentage: 0.5
},
{
label: 'Talents',
backgroundColor: theme.palette.secondary.main,
data: dataProp.talents,
barThickness: 12,
maxBarThickness: 10,
barPercentage: 0.5,
categoryPercentage: 0.5
}
],
labels
};
This is the screenshot the chart created.
I know how to set onclick on legend but how can i set an onClick on labels ?
I Tried this in option but it is not working and giving me error
const options = {
responsive: true,
maintainAspectRatio: false,
animation: false,
cornerRadius: 20,
legend: {
display: false
},
layout: {
padding: 0
},
scales: {
xAxes: [
{
}
],
yAxes: [
{
}
]
},
tooltips: {
},
onClick: function(evt, element) {
if (element.length > 0) {
console.log(element);
// you can also get dataset of your selected element
data.datasets[element[0]._datasetIndex].data[element[0]._index];
}
}
};
All you need to do is just add onClick callback in graph options property
options={{
.....
onClick: function(evt, element) {
if(element.length > 0) {
console.log(element,element[0]._datasetInde)
// you can also get dataset of your selected element
console.log(data.datasets[element[0]._datasetIndex])
}
}}
You need to get ref, and add event getElementAtEvent.
import { Bar } from 'react-chartjs-2'
import { Chart } from 'chart.js'
const BarChart = () => {
const chartRef = useRef<HTMLCanvasElement>(null)
...
return ( <Bar
type='horizontalBar'
data={chartData}
ref={chartRef}
getElementAtEvent={(i: any, event: any) => {
if (chartRef.current) {
const chart = Chart.getChart(chartRef.current)
const clickedElements = chart!.getElementsAtEventForMode(event, 'y',{axis: 'x', intersect: false}, true)
if (clickedElements.length > 0) {
console.log(clickedElements[0].index) // Here clicked label | data index
}
}
}}
options={options}/>
)
}

Victory events not re-rendering chart

I am using Victory for data visualisation in my project. However, while implementing event handlers in my charts, I noticed that while they change the target properties, the charts are never re-rendered so nothing changes.
Below is an example from Victory's documentation, which does not work on my machine:
<div>
<h3>Click Me</h3>
<VictoryScatter
style={{ data: { fill: "#c43a31" } }}
size={9}
labels={() => null}
events={[{
target: "data",
eventHandlers: {
onClick: () => {
return [
{
target: "data",
mutation: (props) => {
const fill = props.style && props.style.fill;
return fill === "black" ? null : { style: { fill: "black" } };
}
}, {
target: "labels",
mutation: (props) => {
return props.text === "clicked" ?
null : { text: "clicked" };
}
}
];
}
}
}]}
data={[{ x: 1, y: 2 },
{ x: 2, y: 3 },
{ x: 3, y: 5 },
{ x: 4, y: 4 },
{ x: 5, y: 7 }]}
/>
</div>
After some debugging, I can confirm that the data and labels properties of the component are changed as a result of the onClick event, but these changes are not actually reflected in the chart. Any solutions?
It seems the issue is caused by having <React.StrictMode> on in the code inside index.js. Removing it solves the problem. I am not exactly sure why though!!

Printing a list by clicking chart Chart js + react

Hi i'm having troubles printing in a alert (by clicking one of the portions), a list of users for a specific answer in chart.js + react here's my chart component
Piechart.js
import React,{ Component } from 'react';
import {Chart} from 'react-chartjs-2';
class Piechart extends Component {
constructor(props){
super(props)
this.chartReference = React.createRef();
this.state = {
data:[]
};
}
async componentDidMount(){
const url = "https://api-tesis-marco.herokuapp.com/api/v1/questiondata/"+this.props.title;
const data = await fetch(url)
.then(response => response.json());
this.setState({data:data});
this.myChart = new Chart(this.chartReference.current,{
type: 'pie',
data:{
labels: this.state.data.map(d=>d.Respuesta),
datasets: [{
data: this.state.data.map(d=>d.porcentaje),
backgroundColor: this.props.colors
}],
},
options: {
title: {
display: true,
text: this.props.title,
fontSize: 20,
fontStyle: 'bold'
},
legend: {
position:'right'
},
onClick: clicked
}
});
function clicked(evt){
var element = this.getElementAtEvent(evt);
if(element[0]){
alert();
}
}
}
render(){
return(
<canvas ref={this.chartReference} />
)
}
}
export default Piechart;
//i having troubles passing the lists data of my request
function clicked(evt){
var element = this.getElementAtEvent(evt);
if(element[0]){
//i don't know what to do here
alert();
}
}
Here is the json response of my request:
Data:
[
{
"Respuesta": "A",
"porcentaje": 7,
"quien": [
"1",
"visita1"
]
},
{
"Respuesta": "B",
"porcentaje": 3,
"quien": [
"coco"
]
},
{
"Respuesta": "C",
"porcentaje": 3,
"quien": [
"Dani3l"
]
},
{
"Respuesta": "D",
"porcentaje": 10,
"quien": [
"Gabi",
"test",
"visita prueba"
]
},
{
"Respuesta": "No ha respondido",
"porcentaje": 76,
"quien": [
"9punto5",
"Colita de algodón",
"KarmenQueen",
"Prueba",
"ancova",
"cehum2",
"chuky",
"dev",
"felipe",
"gabs",
"icom2019",
"invunche",
"john",
"laura",
"marian",
"marti",
"pablazozka",
"prueba",
"test1",
"titicaco",
"visita 1",
"visita test"
]
}
]
in my clicked function how can i pass the "quien" lists for the specific portion of my pie chart?, so in the alert i can print the list of that portion , i'm using this as guide https://jsfiddle.net/u1szh96g/208/ but is difficult for me adapt this to react
well after some mixed tutorials and guides, i came with the solution
Piechart.js:
import React,{ Component } from 'react';
import {Chart} from 'react-chartjs-2';
class Piechart extends Component {
constructor(props){
super(props)
this.chartReference = React.createRef();
this.state = {
data:[]
};
}
async componentDidMount(){
const url = "https://api-tesis-marco.herokuapp.com/api/v1/questiondata/"+this.props.title;
const data = await fetch(url)
.then(response => response.json());
this.setState({data:data});
var datasets = [{data: this.state.data.map(d=>d.Count),
backgroundColor: this.props.colors
},
{
data: this.state.data.map(d=>d.Percent)
},
{
data: this.state.data.map(d=>d.Who)}]
this.myChart = new Chart(this.chartReference.current,{
type: 'pie',
data:{
labels: this.state.data.map(d=>d.Answer),
datasets: [{
data: datasets[0].data,
backgroundColor: datasets[0].backgroundColor
}]
},
options: {
title: {
display: true,
text: this.props.title,
fontSize: 20,
fontStyle: 'bold'
},
legend: {
position:'right'
},
tooltips:{
callbacks: {
title: function(tooltipItem, data) {
return 'Respuesta:'+data['labels'][tooltipItem[0]['index']];
},
label: function(tooltipItem, data) {
return 'Total:'+data['datasets'][0]['data'][tooltipItem['index']];
},
afterLabel: function(tooltipItem) {
var dataset = datasets[1];
var total = dataset['data'][tooltipItem['index']]
return '(' + total+ '%)';
}
},
backgroundColor: '#FFF',
titleFontSize: 16,
titleFontColor: '#0066ff',
bodyFontColor: '#000',
bodyFontSize: 14,
displayColors: false
},
onClick: clicked
}
});
function clicked(evt){
var element = this.getElementAtEvent(evt);
if(element[0]){
var idx = element[0]['_index'];
var who = datasets[2].data[idx];
alert(who);
}
}
}
render(){
return(
<canvas ref={this.chartReference} />
)
}
}
export default Piechart;
as you can see i only set an datasets array outside
var datasets = [{
data: this.state.data.map(d=>d.Count),
backgroundColor: this.props.colors
},
{
data: this.state.data.map(d=>d.Percent)
},
{
data: this.state.data.map(d=>d.Who)}]
this contains all the datasets of the request, then in the chart instance i only pass the dataset i want to plot, then for my question, in the clicked function only call the element of the array wich contains the list of users for the specific answer
Cliked function:
function clicked(evt){
var element = this.getElementAtEvent(evt);
if(element[0]){
var idx = element[0]['_index'];
var who = datasets[2].data[idx];
alert(who);
}
}
i made a custom tooltip as well, but i have an issue with this(with the default tooltip is the same) because i use this component to plot 4 piecharts but when i hover the mouse only 2 of the 4 charts show me the tooltip, the 2 chart who shows the tooltip are random (when refresh localhost pick randomly 2 of the 4 charts), and i don't know what is happend or how to fix this, i hope this is usefull to someone

How to send an array of object as a prop?

I have a state which is an object containing an array and that array contains an object which looks something like this
[{"tone":"negative","value":0},{"tone":"neutral","value":91},{"tone":"positive","value":9}].
So I want to plot a bar chart using only the values from this array of objects. I want to send these values to another component which can be used to plot bar charts dynamically. But I'm not sure how to do it. can someone please show how to send the values to the barchart component and use them in the barchart as well?
This is the code
state={
analysis: {
tonal: [],
anxiety: []
}
}
Analysis = async () => {
//some api call
const {
...tonalAnalysis
} = result.scores;
const tonalArray = Object.entries(tonalAnalysis).reduce(
(carry, [tone, value]) => [
...carry,
{ tone: tone.toLowerCase(), value: parseInt(value) }
],
[]
);
this.setState({
analysis: { ...this.state.analysis, tonal: tonalArray }
});
console.log("Tonal array" + JSON.stringify(this.state.analysis.tonal)); //console logs `[{"tone":"negative","value":0},{"tone":"neutral","value":91},{"tone":"positive","value":9}]`
};
render(){
return {
<BarCharts/> // confused how to send the values as props here
}
the bar chart component where I will use
import React from "react";
import { Bar } from "react-chartjs-2";
import "./App.css";
class BarCharts extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {
labels: [
negative,
neutral,
positive
],
datasets: [
{
label: "Value plotting",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: [65, 59, 80, 81, 56, 55, 40] //want to use the values here dynamically. Don't want these static values
}
]
}
};
}
render() {
const options = {
responsive: true,
legend: {
display: false
},
type: "bar"
};
return (
<Bar
data={this.state.data}
width={null}
height={null}
options={options}
/>
);
}
}
export default BarCharts;
You can create a HighChart wrapper component that can be used for any Highchart graphs.
Note:- every time the data set changes you need to destroy and re-render the graph again in order to make the graph reflect changes.
// #flow
import * as React from "react";
import merge from "lodash/merge";
import Highcharts from "highcharts";
import isEqual from "lodash/isEqual";
export type Props = {
config?: Object,
data: Array<any>,
onRendered?: () => void
};
class HighchartWrapper extends React.PureComponent<Props> {
container: ?HTMLElement;
chart: any;
static defaultProps = {
config: {},
onRendered: () => {}
};
componentDidMount() {
this.drawChart(this.props);
}
componentWillReceiveProps(nextProps: Props) {
const data= [...this.props.data];
if (!isEqual(nextProps.config, this.props.config) || !isEqual(nextProps.data, data)) {
this.destroyChart();
this.drawChart(nextProps);
}
}
destroyChart() {
if (this.chart) {
this.chart.destroy();
}
}
componentWillUnmount() {
this.destroyChart();
}
drawChart = (props: Props) => {
const { config: configProp, data, onRendered } = props;
if (this.container) {
let config = merge({}, configProp);
this.chart = new Highcharts.chart(this.container, { ...{ ...config, ...{ series: [...data] } } }, onRendered);
}
};
render() {
return <div ref={ref => (this.container = ref)} />;
}
}
export default HighchartWrapper;
In order use it for BarChart just pass the appropriate bar chart config.
<HighchartWrapper config={{
chart: {
type: "bar"
}
}}
data={[]}
>
Edit
import React from "react";
import BarChart from "./BarChart";
export default function App() {
return (
<div style={{ width: 400, height: 840 }}>
<BarChart
config={{
chart: {
height: 840,
type: "bar"
},
xAxis: {
categories: ["Positive", "Neutral", "Negative" ],
title: {
text: null
}
},
yAxis: {
min: 0,
title: {
text: "Population (millions)",
align: "high"
},
labels: {
overflow: "justify"
}
}
}}
data={[
{
name: "Series Name",
data: [90, 9, 10]
}
]}
/>
</div>
);
}
Just add your desired props in at component declaration :
<BarCharts data={this.state.analysis}/>
And on your BarChart Component you will need to just extract the values from your arrays, this just in case you need the same structure:
...
this.state = {
data: {
labels: [
negative,
neutral,
positive
],
datasets: [
{
label: "Value plotting",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: extractValues(this.props.data)
}
]
}
...
//This method can be reused in a hook or in a lifecycle method to keep data updated.
const extractValues = (data) => {
return data.map( d => d.value);
}
You can map the array so your code would be:
state={
analysis: {
tonal: [],
anxiety: []
}
}
Analysis = async () => {
//some api call
const {
...tonalAnalysis
} = result.scores;
const tonalArray = Object.entries(tonalAnalysis).reduce(
(carry, [tone, value]) => [
...carry,
{ tone: tone.toLowerCase(), value: parseInt(value) }
],
[]
);
this.setState({
analysis: { ...this.state.analysis, tonal: tonalArray }
});
console.log("Tonal array" + JSON.stringify(this.state.analysis.tonal)); //console logs `[{"tone":"negative","value":0},{"tone":"neutral","value":91},{"tone":"positive","value":9}]`
};
render(){
return {
<BarCharts values={this.state.analysis.tonal.map((entry) => entry.value)}/> // confused how to send the values as props here
}
And your barchart would be:
import React from "react";
import { Bar } from "react-chartjs-2";
import "./App.css";
class BarCharts extends React.Component {
constructor(props) {
super(props);
this.state = {
data: {
labels: [
negative,
neutral,
positive
],
datasets: [
{
label: "Value plotting",
backgroundColor: "rgba(255,99,132,0.2)",
borderColor: "rgba(255,99,132,1)",
borderWidth: 1,
hoverBackgroundColor: "rgba(255,99,132,0.4)",
hoverBorderColor: "rgba(255,99,132,1)",
data: props.values //want to use the values here dynamically. Don't want these static values
}
]
}
};
}
render() {
const options = {
responsive: true,
legend: {
display: false
},
type: "bar"
};
return (
<Bar
data={this.state.data}
width={null}
height={null}
options={options}
/>
);
}
}
export default BarCharts;

Am I using chart.update() correctly when trying to update the chart?

I have a chart created using chartjs and vuechartjs in my Vue project. Data will be passed in via mapGetters from my database. Data will change and the yAxes needs to be updated so that the ticks min and max and stepSize need to change corresponding to the available data being displayed. I wouldn't want my max to be 2500 with a step size of 250 when only displaying max data of 555. I want it to be closer to max 600 with stepSize of 50.
I read the documentation and it says to use chart.update(). I am trying to test this and it says that update cannot be read.
Error in v-on handler: "TypeError: Cannot read property 'update' of undefined"
Here is my code.
export default {
components: {
BarChart,
RoiCalculator
},
data() {
return {
data: [0,0,0,0,0,0,0,0,0,0,0],
maxFeedback: 0,
datacollection: null,
// Configure chart options here
options: {
tooltips: {
//Allows positioning of the tooltip to the event(mouse) position. Custom is the name of the position
//because that is the function created for Chart.Tooltip.positoners
position : 'custom',
callbacks: {
label: function(tooltipItem, data) {
var label = Math.floor(tooltipItem.yLabel*100)/100+" "+data.datasets[tooltipItem.datasetIndex].label;
return label;
}
}
},
maintainAspectRatio: false,
legend: {
//Hides the legend that would normally say NPS scores
display: false
},
// X and Y axes modified here
scales: {
// Allows you to customize the X axis
xAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'Rating',
},
gridLines: {
display: false,
tickMarkLength: 0,
},
ticks: {
padding: 15,
showLabelBackdrop: false
}
}],
// Allows you to customize the Y axis
yAxes: [{
gridLines: {
tickMarkLength: 0,
},
ticks: {
padding: 15,
max: 500,
min: 0,
stepSize: 50
},
}]
},
},
}
},
mounted() {
this.populateFeedback();
},
computed: {
...mapGetters({
filteredFeedback: "initialFeedback"
}),
tid: function() {
return Spark.state.currentTeam.id;
} ,
},
watch: {
filteredFeedback: {
handler(){
this.loadData()
this.getMaxData()
this.resizeChart()
},
},
},
methods: {
...mapActions({
changeInitialFeedback: "changeInitialFeedback",
}),
updateChart(chart){
this.datacollection.datasets[0].data = [100, 200, 400, 600, 700, 1000, 120, 300, 305, 400, 555];
this.chartData.update();
},
loadData(){
this.datacollection = {
labels: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
datasets: [{
label: '',
data: this.sortData(),
backgroundColor: [
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(242, 74, 99)',
'rgb(253, 205, 61)',
'rgb(253, 205, 61)',
'rgb(9, 198, 117)',
'rgb(9, 198, 117)',
],
}]
}
},
resizeChart(){
console.log(this.Chart)
console.log(this.options.scales.yAxes[0].ticks.stepSize,'options')
if(!this.maxFeedback <= 0 && !this.maxFeedback >=100){
this.options.scales.yAxes[0].ticks.max = 100
this.options.scales.yAxes[0].ticks.stepSize = 10
}
else if (this.maxFeedback <= 500){
this.options.scales.yAxes[0].ticks.max = 500
this.options.scales.yAxes[0].ticks.stepSize = 50
}
else (this.maxFeedback <= 2200)
this.options.scales.yAxes[0].ticks.max = 2500
this.options.scales.yAxes[0].ticks.stepSize = 250
},
getMaxData(){
const maxFB = Math.max.apply(Math, this.datacollection.datasets[0].data)
console.log(maxFB, 'hello')
this.maxFeedback = maxFB
},
sortData(){
//Filters through all our filtered feedback data and adds them to each rating
const output=[0,0,0,0,0,0,0,0,0,0,0]
this.filteredFeedback.forEach(function (e) {
output[e.nps_rating] += 1
}
);
return output
},
populateFeedback() {
axios
.get(`/api/metricsPage/all/` + this.tid)
.then(response => {
// Filtering out incomplete data
let filteredFeedback = response.data.feedbacks.filter(feedback => {
return feedback.nps_icon || feedback.has_comments;
});
filteredFeedback = filteredFeedback.map(feedback =>{
feedback.service_rating = Number(feedback.service_rating);
feedback.product_rating = Number(feedback.product_rating);
feedback.delivery_rating = Number(feedback.delivery_rating);
feedback.nps_rating = Number(feedback.nps_rating);
return feedback;
})
// vuex calls to set global state
this.changeInitialFeedback({ initialFeedback: filteredFeedback });
})
.catch(error => {
throw error;
});
},
}
}
</script>
<script>
// This file is what exports the chart used in the index
// Imports and determines type of chart (Line, Bar, etc.)
import { Bar } from 'vue-chartjs'
//Creates custom positioning for the positoning of the tooltip.
Chart.Tooltip.positioners.custom = function(elements, eventPosition) { //<-- custom is now the new option for the tooltip position
/** #type {Chart.Tooltip} */
var tooltip = this;
/* ... */
return {
x: eventPosition.x,
y: eventPosition.y
};
}
export default {
extends: Bar,
props: ['options', 'chartData'],
data() {
return{
chart: this.chartData
}
},
watch: {
//Renders the chart
chartData(){
this.renderChart(this.chartData, this.options)
}
},
}
</script>
I was expecting chart.update() to update but it keeps returning undefined.
The first component you posted refers to this.chartData(), however there is no chartData property on that component. You can force an update by create a ref, then accessing this.$refs.<yourref>.update() within your update handler.

Categories

Resources