react-chartjs chart renders without colors - javascript

I've tried making a radar chart using react-chartjs (https://github.com/reactjs/react-chartjs). It renders, but there are no colors.
What am I missing? I pretty much copied a large chunk of the example at https://reactcommunity.org/react-chartjs/index.html. (I simplified the data to one dataset.)
import React, {PropTypes} from 'react';
import {Grid} from 'react-bootstrap';
const {Radar} = require("react-chartjs");
const ReactDOM = require('react-dom');
function rand(min, max, num) {
var rtn = [];
while (rtn.length < num) {
rtn.push((Math.random() * (max - min)) + min);
}
return rtn;
}
var chartData = {
labels: ["Eating", "Drinking", "Sleeping", "Designing", "Coding", "Cycling", "Running"],
datasets: [
{
label: "My First dataset",
backgroundColor: "rgba(179,181,198,0.2)",
borderColor: "red",
pointBackgroundColor: "rgba(179,181,198,1)",
pointBorderColor: "#fff",
pointHoverBackgroundColor: "#fff",
pointHoverBorderColor: "rgba(179,181,198,1)",
data: [65, 59, 90, 81, 56, 55, 40]
}
]
};
var chartOptions = {
scale: {
reverse: true,
ticks: {
beginAtZero: true
}
}
};
function TasteGraph({rating}) {
//loop through and output one slider and one value per component
return (
<div>
<Radar data={chartData} options={chartOptions}/>
</div>
);
}
TasteGraph.propTypes = {
rating: PropTypes.array
};
TasteGraph.defaultProps = {
rating: []
};
export default TasteGraph;
There doesn't seem to be any imports missing or clear error. I tried surrounding the chartOptions and ChartData with "[" and "]" based on another related SO question.

Replace backgroundColor with fillColor. Propably your borderColor should be also replaced with strokeColor.
See in this jsfiddle. (It uses chart.js without react wrapper - but your properties gave same output as in your screenshot)

Related

Is there a way to change the react-chart-js tooltip only on a graph?

I have the following:
const labels = historicosData.map(historico => {
const localDate = new Date(historico.fechaIngreso);
return localDate.toLocaleString('es-ES', { month: 'long' })
});
//const labels = historicosData.map(({ anio }) => anio);
// const labels = [123, 321, 456, 123, 4568]
const data = {
labels,
datasets: [
{
label: 'Valores históricos',
fill: false,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 10,
pointRadius: 10,
pointHitRadius: 10,
data: historicosData.map(({ valor }) => valor),
},
],
};
And it displays the following graph:
Is there a way where I can change the default message of the tooltip (the one saying 'mayo') for a personalized message?
My main purpose is to make the X bottom axis to display only the months' name and display the whole date when the user's hover over one specific point
You can use the options prop as follows to customize the tooltip title:
const options = {
responsive: true,
plugins:
{
tooltip:
{
callbacks:
{
title: (context) =>
{
return context[0].label
},
}
},
},
}
Then pass options as a prop to your Line component:
<Line options = {options} data = {data} />
In the example above, I'm returning context[0].label which is the label you already see on the x-axis. You can change the return value to anything you want, and you can put other necessary logic within the callback as well.
For example, you may choose to return context[0].parsed.x rather than the label. Or you may choose to use this value to put together the final title to return.
Read more about tooltip configuration in the docs.

make horizontal graph with percentage :react js

I trying to make a horizontal chart with react-chartjs i want each data to show the percentage
import React, { Component } from "react";
import { HorizontalBar } from "react-chartjs-2";
export default class Button extends Component {
render() {
const dataHorBar = {
labels: ["January", "February", "March", "April", "May", "June", "July"],
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
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]
}
]
};
return (
<div>
<HorizontalBar data={dataHorBar} />
</div>
);
}
}
Here is the code of what I have tried
https://codesandbox.io/s/react-chartjs-bar-horizontal-bar-forked-be9wil
I also want to remove the background lines and make the graph more rounded edge
In order to use the feature for having rounded rectangles, you need to update to the v3 of chartjs, therefore, the following code will be working only on this version. But you can adapt it to a previous version, you will just not be able to change the border radius of the rectangle.
You can use the datalabels plugin, in order to display custom text in your chart, and format the label like this:
options: {
plugins: {
datalabels: {
formatter: value => value + " %", // Add the percentage after the value
align: "end",
anchor: "end",
clip: true,
}
}
}
For the shapes, you can use the option borderRadius, to have rounded edges. You can find more information here, but in the end, you just have to specify a value for the borderRadius, in each dataset:
datasets: [
{
label: "My First dataset",
backgroundColor: "#EC932F",
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],
borderRadius: 50, // Give a number
}
]
Finally, for removing the grid lines, you can use this snippet, and pass those options to your chart
options: {
scales: {
x: {
grid: {
display: false // Hide x grid
}
},
y: {
grid: {
display: false // Hide y grid
}
}
}
};
That's it for the ground principle. Here is a live working example, if you really wants to see how to implement it.

Chartjs custom colors not displaying when dataset is changed

I am trying to create 2 distinct line charts which display 2 different datasets. With this, I want to display 2 different colors for each chart.
<div style="display: block" *ngIf='signalRService.data'>
<canvas baseChart id="data1"
[datasets]="signalRService.data1"
[labels]="chartLabels"
[options]="chartOptions"
[legend]="chartLegend"
[chartType]="chartType"
[colors]="colors"
(chartClick)="chartClicked($event)"></canvas>
</div>
<div style="display: block" *ngIf='signalRService.data'>
<canvas baseChart id="data2"
[datasets]="signalRService.data2"
[labels]="chartLabels"
[options]="chartOptions"
[legend]="chartLegend"
[chartType]="chartType"
[colors]="colors"
(chartClick)="chartClicked($event)"></canvas>
</div>
At the moment, I have signalRService.dataX which is containing specific data from the larger signalRService.data. When I separate the data into 2 variables to assign them to different charts, the colors and color settings stop working and revert to their defaults (Light gray with a fill). I also have them both on the same componenent.
Fixes I have tried:
I have tried to use the [data] property instead of [datasets] which hasn't worked, as I can't read signalRService.data[0] because it's undefined.
I tried to create 2 separate arrays for colors, which hasn't worked either.
I have looked into, but haven't really figured out how I can use [datasets]="signalRService.data" and then hide a different dataset for each chart.
The best solution would be if I was able to adjust colors and maintain the rest of the code or to be able to hide a dataset on each graph (I will have 3, so I'd want to hide 2 of 3 datasets). However, I'm open to any ideas, even what I might have "tried" but done incorrectly.
Below is my app.component.ts file in case it's necessary.
import { Component, OnInit } from '#angular/core';
import { SignalRService } from './services/signal-r.service';
import { HttpClient } from '#angular/common/http';
import { ChartOptions } from 'chart.js';
import { Label } from 'ng2-charts';
import * as pluginCrosshair from 'chartjs-plugin-crosshair';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
public chartOptions: (ChartOptions) = {
responsive: true,
spanGaps: false,
animation: {
duration: 0
},
scales: {
// We use this empty structure as a placeholder for dynamic theming.
xAxes: [{}],
yAxes: [
{
id: 'y-axis-0',
position: 'left',
ticks: {
max : 30,
min: -30
}
},
]
},
plugins: {
tooltips: {
mode: "interpolate",
intersect: false,
},
crosshair: {
line: {
color: '#F66', // crosshair line color
width: 2, // crosshair line width
value: '0'
},
sync: {
enabled: false, // enable trace line syncing with other charts
//group: 1, // chart group
suppressTooltips: false // suppress tooltips when showing a synced tracer
},
},
zoom: {
enabled: false,
},
}
};
public chartType: string = 'line';
public chartLegend: boolean = true;
public chartLabels: Label[] = ['0', '1', '2', '3', '4', '5','6','7','8','9','10','11','12','13','14','15','16','17',
'18','19','20','21','22','23','24','25','26','27','28','29','30','31','32','33','34','35','36','37','38','39','40',
'41','42','43','44','45','46','47','48','49','50','51','52','53','54','55','56','57','58','59'];
public chartPlugins = [pluginCrosshair];
public colors: any[] = [{ // grey
backgroundColor: 'rgba(148,159,177,0.2)',
borderColor: 'rgba(148,159,177,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
},
{
backgroundColor: 'rgba(0,100,0,0.2)',
borderColor: 'rgba(0,0,100,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
}];
constructor(public signalRService: SignalRService, private http: HttpClient) { }
ngOnInit() {
this.signalRService.startConnection();
this.signalRService.addTransferChartDataListener();
this.signalRService.addBroadcastChartDataListener();
this.startHttpRequest();
}
private startHttpRequest = () => {
this.http.get('https://localhost:5001/api/chart')
.subscribe(res => {
console.log(res);
})
}
public chartClicked = (event) => {
console.log(event);
this.signalRService.broadcastChartData();
}
}
I actually figured this out. If I replace the reference in the html to the colors array with just the information itself like this
[colors]="
[{
backgroundColor: 'rgba(0,100,0,0.2)',
borderColor: 'rgba(0,0,100,1)',
pointBackgroundColor: 'rgba(148,159,177,1)',
pointBorderColor: '#fff',
pointHoverBackgroundColor: '#fff',
pointHoverBorderColor: 'rgba(148,159,177,0.8)',
fill: false
}]"
and I also change the data1 and data2 variables to slices (using Arrays.slice) of the original super dataset, it works.

Can anyone help me move data from an Axios JSON response to a plot points on a Chart js line chart?

I am working on building a React app that contains a line chart representing the timeline of data recordings from a certain point in time to present day. I am using the JS library Chart js. Specifically the 'react-chartjs-2' plugin. I am using the '/historical/all' path of the following API:
[https://corona.lmao.ninja/docs/?urls.primaryName=version%202.0.0#/][1]
I am successfully retrieving a response from the Axios GET request. But the structuring of the JSON being sent back to me is confusing me when it comes to the implementation I have been following to build the application. I have a lot of the scaffolding in place, but I am struggling to get the data from GET request function to the line chart.
The data is being sent in the following structure:
{
"cases": {
"3/21/20": 304507,
"3/22/20": 336953,
"3/23/20": 378231,
"3/24/20": 418041,
"3/25/20": 467653,
"3/26/20": 529591,
"3/27/20": 593291,
"3/28/20": 660693,
"3/29/20": 720140,
"3/30/20": 782389,
"3/31/20": 857487,
"4/1/20": 932605,
"4/2/20": 1013466,
"4/3/20": 1095917,
"4/4/20": 1176060,
"4/5/20": 1249754,
"4/6/20": 1321481,
"4/7/20": 1396476,
"4/8/20": 1480202,
"4/9/20": 1565278,
"4/10/20": 1657526,
"4/11/20": 1735650,
"4/12/20": 1834721,
"4/13/20": 1904838,
"4/14/20": 1976191,
"4/15/20": 2056054,
"4/16/20": 2152437,
"4/17/20": 2240190,
"4/18/20": 2317758,
"4/19/20": 2401378
},
"deaths": {
"3/21/20": 12973,
"3/22/20": 14651,
"3/23/20": 16505,
"3/24/20": 18625,
"3/25/20": 21181,
"3/26/20": 23970,
"3/27/20": 27198,
"3/28/20": 30652,
"3/29/20": 33925,
"3/30/20": 37582,
"3/31/20": 42107,
"4/1/20": 47180,
"4/2/20": 52983,
"4/3/20": 58787,
"4/4/20": 64606,
"4/5/20": 69374,
"4/6/20": 74565,
"4/7/20": 81937,
"4/8/20": 88338,
"4/9/20": 95521,
"4/10/20": 102525,
"4/11/20": 108502,
"4/12/20": 114090,
"4/13/20": 119481,
"4/14/20": 125983,
"4/15/20": 134176,
"4/16/20": 143800,
"4/17/20": 153821,
"4/18/20": 159509,
"4/19/20": 165043
},
"recovered": {
"3/21/20": 91682,
"3/22/20": 97889,
"3/23/20": 98341,
"3/24/20": 107890,
"3/25/20": 113604,
"3/26/20": 121966,
"3/27/20": 130659,
"3/28/20": 138949,
"3/29/20": 148616,
"3/30/20": 164100,
"3/31/20": 176442,
"4/1/20": 191853,
"4/2/20": 208528,
"4/3/20": 223621,
"4/4/20": 243575,
"4/5/20": 257000,
"4/6/20": 273259,
"4/7/20": 296263,
"4/8/20": 324507,
"4/9/20": 348813,
"4/10/20": 370241,
"4/11/20": 395521,
"4/12/20": 414599,
"4/13/20": 440897,
"4/14/20": 466051,
"4/15/20": 502053,
"4/16/20": 532409,
"4/17/20": 557798,
"4/18/20": 581355,
"4/19/20": 612056
}
}
I would like for each category (cases, deaths, recovered) to represent a line on the chart showing the progression over time, but I'm unsure how to handle it. With the intention being that the dates would be the X-axis and the points would be plotted in a different colored line for each.
Would anyone be able to help with this at all? I would greatly appreciate some guidance. Below are the two primary files corresponding to the Chart and API handling:
index.js
export const fetchDailyData = async () => {
try {
const { data } = await axios.get(`${url}/historical/all`);
const labels = Object.keys(data.cases);
const cases = labels.map((name) => data.cases[name]);
const deaths = labels.map((name) => data.deaths[name]);
const recovered = labels.map((name) => data.recovered[name]);
return {labels, cases, deaths, recovered};
} catch (error) {
return error;
}
}
Chart.jsx
import React, { useState, useEffect } from 'react';
import { Line, Bar } from 'react-chartjs-2';
import { fetchDailyData } from '../../api';
import styles from './Chart.module.css';
const Chart = ({data: { labels, cases, deaths, recovered }}) => {
const [dailyData, setDailyData] = useState([]);
useEffect(() => {
const fetchAPI = async () => {
setDailyData(await fetchDailyData());
}
fetchAPI();
}, []);
const lineChart = (
<Line data = {
{
labels,
datasets: [{
data:cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true,
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true,
},
{
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true,
}],
}
}
/>
);
return (
<div className = { styles.container }>
{lineChart}
</div>
);
};
export default Chart;
Here is a complete solution:
// Create the chartData state
const [chartData, setChartData] = useState();
// in your fetch function, convert the data to chartData
const labels = Object.keys(data.cases);
const cases = labels.map((name) => data.cases[name]);
const deaths = labels.map((name) => data.deaths[name]);
const recovered = labels.map((name) => data.recovered[name]);
setChartData({
labels,
datasets: [{
data: cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true
}, {
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true
}]
})
// Now render your chart (but make sure chartData exists)
return (
<div className = { styles.container }>
{chartData &&
<Line data={chartData} />
}
</div>
);
First extract the x labels:
const labels = Object.keys(dailyData.cases);
Then extract the y values for each serie:
const cases = Object.keys(dailyData.cases).map((name) => dailyData.cases[name]);
const deaths = Object.keys(dailyData.deaths).map((name) => dailyData.deaths[name]);
const recovered = Object.keys(dailyData.recovered).map((name) => dailyData.recovered[name]);
Then assemble everything into a chart js object:
<Line data = {
labels,
datasets: [{
data: cases,
label: 'Infected',
borderColor: '#3333ff',
fill: true
}, {
data: deaths,
label: 'Deaths',
borderColor: 'red',
backgroundColor: 'rgba(255, 0, 0, 0.5)',
fill: true
}, {
data: recovered,
label: 'Recovered',
borderColor: 'green',
backgroundColor: 'rgba(0, 255, 0, 0.5)',
fill: true
}]
}
/>

Issue While Passing Dynamic Datas in React Chart Js 2

I have successfully passed dynamic datas to React Chart JS 2 but i am having problem displaying it.
Please find the attached screenshot of the chart.
I am trying to make a line chart for all the expenses vs month. As you can see there are two arrays that is visible in the console of the screenshot. One is of Amount spent and corresponding month it was spent can be seen in the array below it. Eg: 529 was spent on May and 100 was spent on April.
Here is my Chart.js
import React from 'react';
import {connect} from 'react-redux';
import {Line} from 'react-chartjs-2';
import moment from 'moment';
const Chart = (props) => {
console.log(props.expenses);
const amount = props.expenses.map((expense) => {
// console.log(expense.amount);
// console.log(moment(expense.createdAt).format('MMMM'));
return expense.amount;
});
console.log(amount);
const createdAt = props.expenses.map((expense) => {
const arr_createdAt = expense.createdAt;
return moment(arr_createdAt).format('MMMM');
});
console.log(createdAt);
const data = {
labels: **createdAt**,
datasets: [
{
label: 'My First dataset',
fill: false,
lineTension: 0.1,
backgroundColor: 'rgba(75,192,192,0.4)',
borderColor: 'rgba(75,192,192,1)',
borderCapStyle: 'butt',
borderDash: [],
borderDashOffset: 0.0,
borderJoinStyle: 'miter',
pointBorderColor: 'rgba(75,192,192,1)',
pointBackgroundColor: '#fff',
pointBorderWidth: 1,
pointHoverRadius: 5,
pointHoverBackgroundColor: 'rgba(75,192,192,1)',
pointHoverBorderColor: 'rgba(220,220,220,1)',
pointHoverBorderWidth: 2,
pointRadius: 1,
pointHitRadius: 10,
data: **amount**
}
]
};
return (
<div>
<div className = "page-header">
<div className = "content-container">
<h1 className = "page-header__title">CHART</h1>
</div>
</div>
<div className = "content-container">
<h2>Line Example</h2>
<Line data={data} />
</div>
</div>
)};
const mapStateToProps = (state) => {
return {
expenses : state.expenses
};
}
export default connect(mapStateToProps)(Chart);
What i want to do is bucket all the expenses that was spent on May and dispaly total expense sum in May Line and do same for other months as well.
Any help is much appreciated.
Thank You
Try this:
`let reducedValue = props.expenses.reduce((acc, item) => {
let index = acc.findIndex(accItem => moment(accItem.createdAt).format('MMM') === moment(item.createdAt).format('MMM'));
if(index < 0){
acc.push({...item});
} else {
acc[index].amount += item.amount;
}
return acc;
}, []);
let amount = reducedValue.map(item => item.amount);
let createdAt = reducedValue.map(item => moment(item.createdAt).format('MMM'));
`

Categories