Creating a ChartJS line chart is easy. What’s not easy, is creating a chartjs line chart that matches the mock. I’ve never seen a design that matches something that’s nearly ready built—in entirety. It always differs. And that’s what’s happening here.
This chartjs line chart is totally customized.
- toggle the x axis
- toggle the y axis
- toggle the grid lines
- change the amount of grid lines for better accuracy
- do it all with an elegant menu of said options
- add a dynamic JSON feed indicative of one or more APIs
Start with the data. This is what both lines expect. Followed by the data in the options menu. I initially thought using JSON for everything was time consuming and complex. Now it’s my preference.
** Line Data
{
"chartData": [
{
"line": [10, 50, 25, 70, 40, 10, 90, 67, 88, 112, 115, 120]
},
{
"line": [20, 30, 25, 35, 40, 64, 65, 67, 75, 100, 100, 100]
}
]
}
** Options Menu Data
{
"menuOptions": [
{
"item": "Y Axis",
"checkMark": true
},
{
"item": "X Axis Labels",
"checkMark": true
},
{
"item": "X Axis Grid Lines",
"checkMark": true
},{
"lineOptions": [
{
"value": 7,
"percent": 14.28
},
{
"value": 10,
"percent": 10
},
{
"value": 15,
"percent": 6.67
},
{
"value": 20,
"percent": 5
}
]
}
]
}
Then in the line chart TS file, add the variables. Afterwards, pipe the JSON into two separate arrays. This occurs OnInit.
chart: any;
chartDataArray: any = []; // Chart Data
optionsArray: any = []; // Menu Options
optionsPanel: boolean; // Menu Status
xGridVisible: boolean = true; // X Axis Lines
yLabelVisible: boolean = true; // Y Axis Label
selectedCheckbox: any; // InnerHTML of Selected Checkbox in Legend
date: any = new Date();
month: any = this.date.getMonth();
months: any = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
xAxisVisible: boolean = true;
currentMonth: any = this.months[this.month];
ngOnInit() {
// Push JSON to array
for (let key in data.chartData) {
if (data.chartData.hasOwnProperty(key)) {
this.chartDataArray.push(data.chartData[key]);
}
}
// Push JSON to options array
for (let key in jsonOptions.menuOptions) {
if (jsonOptions.menuOptions.hasOwnProperty(key)) {
this.optionsArray.push(jsonOptions.menuOptions[key]);
}
}
}
Then in AfterViewInit, configure the chartjs line chart. This should be get us up and running.
ngAfterViewInit() {
let data: any,
options: any,
ctx: any = document.getElementById('lineChart') as HTMLElement;
data = {
datasets: [
{
label: 'Product A',
backgroundColor: '',
borderColor: '#02a9f7',
data: this.chartDataArray[0].line,
fill: false,
},
{
label: 'Product B',
fill: false,
backgroundColor: '',
borderColor: '#02577a',
data: this.chartDataArray[1].line,
},
],
fill: false, // Change this to true, add rgba(...) in datasets background color
};
data.labels = this.months;
options = {
maintainAspectRatio: false, // Enables custom canvas dimension
responsive: true,
layout: {
padding: {
top: 20,
right: 20,
left: 20,
bottom: 0,
},
},
title: {
display: false,
text: '',
},
tooltips: {
mode: 'index',
intersect: false,
},
hover: {
mode: 'nearest',
intersect: true,
},
legend: {
display: false,
position: '',
},
scales: {
yAxes: [
{
ticks: {
display: false,
},
gridLines: {
display: false,
},
},
],
xAxes: [
{
ticks: { display: this.xAxisVisible },
gridLines: {
display: false,
},
},
],
},
};
this.chart = new Chart(ctx, {
type: 'line',
data: data,
options: options,
});
// 10 line spaced 10% apart. See options.json
this.generateXgridLines(10, 10);
}
Just about everything thus far applies to the canvas tag. Though the markup is a bit heavy, it all relates to the customization of thereof. It’s more of a creative process than a technical one. One in which I enjoy to be honest. It’s an art. And this charting library makes it easier to bypass the hard stuff. Yes, this is written for version 2, but I think it’s the logic behind the project vs the actual code. One could do the same thing with HTML and vanilla JS. Or Vue. Or React. From one developer to the next. Hope you found this thought provoking. Please see a working version of Chartjs Line Chart on Stackblitz here.
Leave a Reply