Building with React... Trying to use outside method called on button click
Attempting to set mappoints to invisible. I have tried using:
.hide()
.setVisible
and using .update() to set 'visible' to false
I am able to reference the chart and the mappoint using the included definition in the package markdown:
let chart = this.refs.chart.getChart();
and in my render:
<ReactHighmaps config={config} ref="chart" />
Attempted:
chart.series[2].event.update({visible: false}) >> Error: Highchart.js:27 Uncaught TypeError: Cannot read property 'update' of
undefined
chart.plotOptions.mappoint.events.hide() >> TypeError: Cannot read property 'mappoint' of undefined
chart.series[2].setVisible(false, true) >> No Error in Console but nothing happens
chart.series[2].hide() >> No Error in Console but nothing happens And a few other variations.
ReactHighmaps.Highcharts.hide(chart.series[0]) >> Error that this isn't a function
There is a lot going on for me to make a JSbin...
Testing in Chrome
When I am inspecting the console.log of the mappoints I see that the method .setVisible() project path is:
.proto.proto.proto.setVisible
chart configuration (options):
const config = {
title: {
text: 'ZCTA with Metric Data'
},
chart: {
height: '600 px',
borderWidth: 1,
borderColor: 'silver',
borderRadius: 3,
shadow: true
},
mapNavigation: {
enabled: true
},
tooltip: {
enabled: false
},
plotOptions: {
map: {
showInLegend: false
},
mappoint: {
showInLegend: false,
},
mapline: {
enabledMouseTracking: false,
showInLegend: false
}
},
series: [{
mapData: MapData,
name: 'test',
data: County,
joinBy: ['fips', 'code'],
animation: true,
tooltip: {
pointFormat: '<b>{point.name}</b>'
},
borderColor: 'black',
borderWidth: 0.2,
states: {
hover: {
borderWidth: 0.5
},
select: {
color: 'yellow'
}
},
allowPointSelect: true,
cursor: 'pointer'
},
{
type: 'mapline',
name: 'State borders',
data: lines,
color: 'black',
states: {
hover: {
borderWidth: 0.5
}
},
allowPointSelect: false
},
{
type: 'mappoint',
name: 'zcta',
color: Highcharts.getOptions().colors[1],
data: Data,
boostThreshold: 500,
}]
For component render:
<ReactHighmaps config={config} ref="chart" />
Any suggestions?
Using React, Highcharts, and React-Highcharts (npm)
I was unable to get any Highcharts(Highmaps) API methods to work, but was able to drill down to update the state object.
This led me to Redux as a state management tool because I realize it would be better to have this controlled in an application state versus React component.
Here is my action and reducer:
export const SHOW_POINTS = 'SHOW_POINTS'
export function showPoints(configuration){
return {
type: SHOW_POINTS,
payload: configuration
};
}
const PointsMapConfig = (state = initialState, action) => {
switch (action.type){
case SHOW_POINTS:
return console.log(state.mapConfig.series[2]), { ...state,
mapConfig: {
series: [
...state.mapConfig.series.filter((el, index) => index !== 2), {
...state.mapConfig.series[2],
visible: true
}
]
}
}
default:
return state;
}
}
export default PointsMapConfig
onClick access with mapDispatchToProps:
function mapDispatchToProps(dispatch){
return bindActionCreators({
showPoints: showPoints
}, dispatch);
}
<Buttons style="success" classN="btn btn-secondary" text="test" onButtonClick={()=> this.props.showPoints( )} />
Related
I am trying to hide the legend of my chart created with Chart.js.
According to the official documentation (https://www.chartjs.org/docs/latest/configuration/legend.html), to hide the legend, the display property of the options.display object must be set to false.
I have tried to do it in the following way:
const options = {
legend: {
display: false,
}
};
But it doesn't work, my legend is still there. I even tried this other way, but unfortunately, without success.
const options = {
legend: {
display: false,
labels: {
display: false
}
}
}
};
This is my full code.
import React, { useEffect, useState } from 'react';
import { Line } from "react-chartjs-2";
import numeral from 'numeral';
const options = {
legend: {
display: false,
},
elements: {
point: {
radius: 1,
},
},
maintainAspectRatio: false,
tooltips: {
mode: "index",
intersect: false,
callbacks: {
label: function (tooltipItem, data) {
return numeral(tooltipItem.value).format("+0,000");
},
},
},
scales: {
xAxes: [
{
type: "time",
time: {
format: "DD/MM/YY",
tooltipFormat: "ll",
},
},
],
yAxes: [
{
gridLines: {
display: false,
},
ticks: {
callback: function(value, index, values) {
return numeral(value).format("0a");
},
},
},
],
},
};
const buildChartData = (data, casesType = "cases") => {
let chartData = [];
let lastDataPoint;
for(let date in data.cases) {
if (lastDataPoint) {
let newDataPoint = {
x: date,
y: data[casesType][date] - lastDataPoint
}
chartData.push(newDataPoint);
}
lastDataPoint = data[casesType][date];
}
return chartData;
};
function LineGraph({ casesType }) {
const [data, setData] = useState({});
useEffect(() => {
const fetchData = async() => {
await fetch("https://disease.sh/v3/covid-19/historical/all?lastdays=120")
.then ((response) => {
return response.json();
})
.then((data) => {
let chartData = buildChartData(data, casesType);
setData(chartData);
});
};
fetchData();
}, [casesType]);
return (
<div>
{data?.length > 0 && (
<Line
data={{
datasets: [
{
backgroundColor: "rgba(204, 16, 52, 0.5)",
borderColor: "#CC1034",
data: data
},
],
}}
options={options}
/>
)}
</div>
);
}
export default LineGraph;
Could someone help me? Thank you in advance!
PD: Maybe is useful to try to find a solution, but I get 'undefined' in the text of my legend and when I try to change the text like this, the text legend still appearing as 'Undefindex'.
const options = {
legend: {
display: true,
text: 'Hello!'
}
};
As described in the documentation you linked the namespace where the legend is configured is: options.plugins.legend, if you put it there it will work:
var options = {
type: 'line',
data: {
labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
datasets: [{
label: '# of Votes',
data: [12, 19, 3, 5, 2, 3],
borderColor: 'pink'
}
]
},
options: {
plugins: {
legend: {
display: false
}
}
}
}
var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
<canvas id="chartJSContainer" width="600" height="400"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.js"></script>
</body>
On another note, a big part of your options object is wrong, its in V2 syntax while you are using v3, please take a look at the migration guide
Reason why you get undefined as text in your legend is, is because you dont supply any label argument in your dataset.
in the newest versions this code works fine
const options = {
plugins: {
legend: {
display: false,
},
},
};
return <Doughnut data={data} options={options} />;
Import your options value inside the charts component like so:
const options = {
legend: {
display: false
}
};
<Line data={data} options={options} />
I'm using Vue Chart JS v3.5.1 in my Nuxt JS/Vue project, and I've noticed that when trying to use options and pass them as a prop, nothing happens, the chart defaults back to the chart's default settings despite me overwriting settings.
I've got several files:
plugins/LineChart.js
components/LineChart.vue
plugins/LineChart.js
import { Line, mixins } from 'vue-chartjs'
const { reactiveProp } = mixins
export default {
extends: Line,
mixins: [reactiveProp],
computed: {
localOptions: function() {
return this.chartOptions
},
localData: function() {
console.log(`data: ${this.chartData}`)
return this.chartData
}
},
mounted () {
this.renderLineChart()
},
methods: {
/*
** Render a line chart
*/
renderLineChart () {
// this.chartdata is created in the mixin.
// If you want to pass options please create a local options object
this.renderChart(this.localData, this.localOptions)
}
},
watch: {
chartData: {
handler: function (val, oldVal) {
this._data._chart.destroy()
this.renderLineChart()
},
deep: true
},
chartOptions: {
handler: function (val, oldVal) {
this.localOptions = val
},
deep: true
}
}
}
components/LineChart.vue
<template>
<div>
<line-chart :chart-data="customChartData" :chart-options="customChartOptions" class="data-chart"></line-chart>
</div>
</template>
<style>
.data-chart canvas {
width: 100% !important;
height: auto !important;
}
</style>
<script>
import LineChart from '~/plugins/LineChart.js'
export default {
components: {
LineChart
},
props: {
labels: {
type: Array,
default: null
},
datasets: {
type: Array,
default: null
},
options: {
type: Object,
default: () => ({})
}
},
data () {
return {
customChartData: {},
customChartOptions: {}
}
},
mounted () {
this.fillData()
},
methods: {
fillData () {
this.customChartData = {
labels: this.labels,
datasets: this.datasets
}
this.customChartOptions = {
options: this.options
}
}
}
}
</script>
My usage, is then reasonably simple, yet I'm not getting my options to show?
<LineChart
:options="{
responsive: true,
maintainAspectRatio: false,
legend: {
display: false
},
scales: {
xAxes: [{
gridLines: {
display: false
},
ticks: {
autoSkip: true,
maxTicksLimit: 3,
maxRotation: 0,
minRotation: 0
}
}],
yAxes: [{
display: true,
gridLines: {
display: true,
color: '#f3f5f6'
}
}]
},
elements: {
point: {
radius: 0,
hitRadius: 35
}
}
}"
:labels="['test']"
:datasets="[{
fill: false,
borderWidth: 2.5,
pointBackgroundColor: '#fff',
borderColor: '#5046e5',
data: [500,
}]"
/>
What am I doing wrong?
UPDATE
In addition, I seem to only have the first chart out of many charts on the page show data, why would only one chart in a series of charts show data, I've got a key on each one.
in your fillData it looks like you assign the options wrong. Vue Chartjs expects an object with the options in it and not an object with an field options with the options.
If you change: this.customChartOptions = {options: this.options} to: this.customChartOptions = this.options it should work
For the past couple days, I was struggling to use this highchart map type in my react project
https://jsfiddle.net/26tbkjov//
Can some one please help me out?
Please check what I achieved until now:
https://codesandbox.io/s/highcharts-react-demo-0m5ux
I am using those highcharts npm packages
"highcharts": "^7.1.2",
"highcharts-react-official": "^2.2.2",
I have tried many things and ended up in a dead path.. the following is the last thing i have tried:
import React from "react";
import mapData from '../../api/mapData';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
require('highcharts/modules/map')(Highcharts);
class MyMap extends React.Component {
constructor(props) {
super(props);
this.state = {
mapValues: [],
modalClassic: false,
};
this.mapData = new mapData();
// preparing the config of map with empty data
this.options = {
title: {
text: 'Widget click by location',
style: {
color: '#fff'
},
},
chart:{
backgroundColor: 'transparent',
type: 'map',
map: null,
},
mapNavigation: {
enabled: true,
enableButtons: false
},
credits: {
enabled: false
},
colorAxis: {
dataClasses: [
{
from: 1,
color: '#C40401',
name: 'widget name one'
}, {
from: 2,
color: '#0200D0',
name: 'widget name two'
}
]
},
tooltip: {
pointFormatter: function() {
return this.name;
}
},
legend: {
align: 'right',
verticalAlign: 'top',
x: -100,
y: 70,
floating: true,
layout: 'vertical',
valueDecimals: 0,
backgroundColor: ( // theme
Highcharts.defaultOptions &&
Highcharts.defaultOptions.legend &&
Highcharts.defaultOptions.legend.backgroundColor
) || 'rgba(255, 255, 255, 0.85)'
},
series: [{
name: 'world map',
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.postal-code}',
style: {
textTransform: 'uppercase'
}
},
tooltip: {
ySuffix: ' %'
},
cursor: 'pointer',
joinBy: 'postal-code',
data: [],
point: {
events: {
click: function(r){
console.log('click - to open popup as 2nd step');
console.log(r);
}
}
}
}]
};
}
/*
* Before mounting the component,
* update the highchart map options with the needed map data and series data
* */
componentWillMount = () => {
this.mapData.getWorld().then((r)=>{
this.setState({'mapData': r.data}, ()=>{
this.options.series[0].data = []; //make sure data is empty before fill
this.options['chart']['map'] = this.state.mapData; // set the map data of the graph (using the world graph)
// filling up some dummy data with values 1 and 2
for(let i in this.state.mapData['features']){
let mapInfo = this.state.mapData['features'][i];
if (mapInfo['id']) {
var postalCode = mapInfo['id'];
var name = mapInfo['properties']['name'];
var value = i%2 + 1;
var type = (value === 1)? "widget name one" : "widget name two";
var row = i;
this.options.series[0].data.push({
value: value,
name: name,
'postal-code': postalCode,
row: row
});
}
}
// updating the map options
this.setState({mapOptions: this.options});
});
});
}
render() {
return (
<div>
{(this.state.mapData)?
<HighchartsReact
highcharts={Highcharts}
constructorType={'mapChart'}
options={(this.state.mapOptions)? this.state.mapOptions: this.options}
/>
: ''}
</div>
);
}
}
export default MyMap;
If you want to use the USA map, you need to change the url to: "https://code.highcharts.com/mapdata/countries/us/us-all.geo.json" and the postal-code from US.MA to MA:
this.mapData.getWorld().then(r => {
...
for (let i in this.state.mapData["features"]) {
...
var postalCode = mapInfo.properties["postal-code"];
...
}
...
});
Live demo: https://codesandbox.io/s/highcharts-react-demo-jmu5h
To use the word map, you need to also change the part related with the postal-code and joinBy property:
series: [{
joinBy: ['iso-a2', 'code'],
...
}]
this.mapData.getWorld().then(r => {
...
for (let i in this.state.mapData["features"]) {
let mapInfo = this.state.mapData["features"][i];
if (mapInfo["id"]) {
var code = mapInfo["id"];
...
this.options.series[0].data.push({
"code": code,
...
});
}
}
...
});
Live demo: https://codesandbox.io/s/highcharts-react-demo-sxfr2
API Reference: https://api.highcharts.com/highmaps/series.map.joinBy
I am trying to integrate highcarts inside the react component.
Here is my code for the react component
import * as Highcharts from 'highcharts/highmaps'
class RealTime extends Component {
componentDidMount() {
$.getJSON( 'https://cdn.jsdelivr.net/gh/highcharts/highcharts#v7.0.0/samples/data/world-population-density.json',
function(data) {
$.each(data, function() {
this.value = this.value < 1 ? 1 : this.value
})
Highcharts.mapChart('world_map', {
chart: {
map: 'custom/world'
},
title: {
text: 'Fixed tooltip with HTML'
},
legend: {
title: {
text: 'Population density per kmĀ²',
style: {
color:
(Highcharts.theme && Highcharts.theme.textColor) || 'black'
}
}
},
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
series: [
{
data: data,
mapData: Highcharts.maps['custom/world'],
joinBy: ['iso-a3', 'code3'],
name: 'Population density',
states: {
hover: {
color: '#a4edba'
}
}
}
]
})
}
)
}
render() {
return (
<div>
<div className="map_bg" id="world_map"/>
</div>
)
}
}
But the above code does not show either the map or any error in my react component . Can Anyone please help me
What i am missing here?
Thank you!!!
You need to add and import the word.js script:
import Highcharts from "highcharts/highmaps";
import customWord from "./word.js";
Live demo: https://codesandbox.io/s/v0x5zx6q05
Also, I can recommend you to use highcharts-react-official wrapper: https://www.npmjs.com/package/highcharts-react-official
I'm trying to create a heat map using Highcharts but it's not loading properly (just lines instead of the heat map itself).
I'm loading the data from a JSON file:
chart: {
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1
},
xAxis: {
categories: $scope.loadDays()
},
yAxis: {
categories: $scope.loadHours(),
title: null,
reversed: true
},
series: [{
name: null,
borderWidth: 1,
data: [],
dataLabels: {
enabled: true,
color: '#000000'
}
}]
$scope.getHeatMapData = function(data) {
var response = [];
$scope.data = data;
if(data && $scope.data.timestamps && $scope.data.info) {
$scope.data.timestamps.forEach(function(element, index) {
if ($scope.data.info[index]) {
response.push([
moment(element).day(),
moment(element).hour(),
$scope.data.info[index]
]);
}
});
}
return response;
};
The data is being logged correctly to the console but, for some reason, the heat map isn't loading.
I've also created a Plunker where you can see its behavior.
Any ideas?
I was making a mistake when reloading the chart. I just had to add the type to the event:
chartConfig.chart = { type: 'heatmap', events: { load: callback } };
Plunker