Visualize Your Data: Showcasing Interactive Charts for Numerical Data using Charts JS Library (Part 23) in Your Angular-15 Ionic-7 App
Welcome back to our ongoing series on building a multiplatform application with Angular-15 and Ionic-7! Throughout this journey, we have explored various aspects of app development, including authentication, data management, task organization, calendar integration, event management, media management, UI customization, enhanced user authentication, real-time data manipulation, creating a selectable and searchable data list, and building a notepad-style rich text editor. Today, in Part 23, we will focus on visualizing numerical data as interactive charts using the Charts JS library.
Charts and graphs are powerful tools for representing and analyzing numerical data. By incorporating the Charts JS library into our Angular-15 Ionic-7 app, we can create dynamic and interactive charts that enable users to explore and interpret data effectively.
In this installment, we will guide you through the process of displaying numerical data as interactive charts using the Charts JS library. We will start by integrating the library into our app and configuring it to suit our needs.
Next, we will explore the various chart types available in Charts JS, such as bar charts, line charts, pie charts, and more. We will demonstrate how to populate the charts with data and customize them to enhance their visual appeal and usability.
Throughout this tutorial, we will emphasize best practices for data visualization, chart configuration, and user interaction. By the end of this article, you will have a solid understanding of how to display numerical data as interactive charts using the Charts JS library, enhancing the data analysis capabilities of your Angular-15 Ionic-7 app.
So, join us in Part 23 of our series as we dive into the exciting world of data visualization. Together, let's harness the power of the Charts JS library to create visually appealing and interactive charts within our application.
Tutorial
Here I have created an analytics page where students can view their progress over the semesters in various modules. For this, I have used the Chats JS library from Angular Charts Demo (valor-software.com) and installed it using the npm install --save ng2-charts
and npm install --save chart.js
which will install the Angular Charts package in the project. Next, I will use the documentation provided on their website to build multiple kinds of charts on the analytics page.
In main.ts
file, I will import the respective angular modules for this package in the following way:
import { ChartEvent } from 'chart.js';
import { NgChartsModule, BaseChartDirective } from 'ng2-charts';
bootstrapApplication(AppComponent, {
providers: [
AuthGuard,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
importProvidersFrom(
...
NgChartsModule.forRoot(),
BaseChartDirective,
...
],
});
Then I will create the analytics page with the command ionic generate page pages/analytics where I won’t write any logic but simply import components of each kind of chart and simply display it in the template file.
So, I will begin creating the first chart i.e. the line chart which will demonstrate the GPA Performance over semesters. I will create the component with the command ionic generate component components/line-chart
and write the logic based on documentation from Angular Charts Demo (valor-software.com) in line-chart.component.ts file in the following way:
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartConfiguration, ChartEvent, ChartType } from 'chart.js';
import { BaseChartDirective, NgChartsModule } from 'ng2-charts';
import { default as Annotation } from 'chartjs-plugin-annotation';
import { default as DataLabelsPlugin } from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, FormsModule, CommonModule, NgChartsModule],
selector: 'app-line-chart',
templateUrl: './line-chart.component.html',
styleUrls: ['./line-chart.component.scss'],
})
export class LineChartComponent implements OnInit {
// <!-- GPA Performance over semesters in line chart. Score on y and sems on x axis. -->
@ViewChild(BaseChartDirective) chart?: BaseChartDirective;
constructor() {}
ngOnInit() {}
public lineChartData: ChartConfiguration['data'] = {
datasets: [
{
data: [3.2, 2.5, 1.5, 2.8, 1.8, 3.8, 2.4],
label: '2023',
fill: 'origin',
},
{
data: [1.5, 2.5, 1.2, 2.1, 3.1, 1.8, 2.3],
label: '2022',
fill: 'origin',
},
],
labels: ['Sem 1', 'Sem 2', 'Sem 3', 'Sem 4', 'Sem 5', 'Sem 6', 'Sem 8'],
};
public lineChartOptions: ChartConfiguration['options'] = {
elements: {
line: {
tension: 0.5,
},
},
scales: {
// We use this empty structure as a placeholder for dynamic theming.
y: {
position: 'left',
beginAtZero: true,
max: 4.0,
},
},
plugins: {
legend: { display: true, position: 'bottom' },
},
};
public lineChartType: ChartType = 'line';
// events
public chartClicked({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
}
In the eabove code, the @ViewChild
decorator is used to inject a reference to the BaseChartDirective
class which is used to interact with the chart. The lineChartData
variable defines an object with two datasets, one for each year (2022 and 2023), with data points for each semester and a label for each dataset.
The lineChartOptions
variable defines an object with options to customize the appearance of the chart. The elements
property defines options for the lines in the chart. The scales
property defines options for the axes, including the y
axis which is positioned on the left, begins at zero, and has a maximum value of 4.0. The plugins
property defines options for plugins, including the legend
plugin which displays a legend at the bottom of the chart. The lineChartType
variable specifies that the chart should be a line chart.
Next, I will write the template for this in line-chart.component.html file like this:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Semester Wise GPA</ion-card-subtitle>
<ion-card-title>Progress</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="lineChartData"
[options]="lineChartOptions"
[type]="lineChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"
></canvas>
</ion-card-content>
</ion-card>
The above code represents an ion-card
element that contains a line chart implemented using the Chart.js
library. The ion-card-content
element is used to contain the chart and other content related to the card. The canvas
element is used to render the line chart. The baseChart
attribute is used to apply the Chart.js
library to the canvas. The class
attribute is set to chart
to apply CSS styling to the chart.
The chart data is passed in using the [data]
binding with the value of the lineChartData
property of the LineChartComponent
class.
The chart options are passed in using the [options]
binding with the value of the lineChartOptions
property of the LineChartComponent
class.
The chart type is passed in using the [type]
binding with the value of the lineChartType
property of the LineChartComponent
class.
The (chartHover)
and (chartClick)
events are bound to the chartHovered()
and chartClicked()
methods respectively of the LineChartComponent
class to handle user interaction events on the chart.
Next, I will import this component in the analytics.page.ts file and place it in the analytics.page.html file in the following way:
import { LineChartComponent } from 'src/app/components/line-chart/line-chart.component';
<ion-header [translucent]="true">
<ion-toolbar>
<ion-title>Analytics</ion-title>
<ion-buttons slot="start">
<ion-back-button defaultHref="/"></ion-back-button>
</ion-buttons>
<ion-buttons slot="end">
<ion-menu-button menu="main-menu"></ion-menu-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content [fullscreen]="true">
<ion-header collapse="condense">
<ion-toolbar>
<ion-title size="large">Analytics</ion-title>
</ion-toolbar>
</ion-header>
<!-- GPA Performance over semesters in line chart. Score on y and sems on x axis. -->
<app-line-chart></app-line-chart>
</ion-content>
And this will display the line chart on the analytics page.
Now, I will create a pie chart (Angular Charts Demo (valor-software.com)) that will demonstrate Latest GPA Distribution by first crating a component via ionic generate component components/pie-chart
and write the logic in pie-chart.component.ts
file in the following way:
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartConfiguration, ChartData, ChartEvent, ChartType } from 'chart.js';
import { BaseChartDirective, NgChartsModule } from 'ng2-charts';
import DatalabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, CommonModule, FormsModule, NgChartsModule],
selector: 'app-pie-chart',
templateUrl: './pie-chart.component.html',
styleUrls: ['./pie-chart.component.scss'],
})
export class PieChartComponent implements OnInit {
@ViewChild(BaseChartDirective) chart: BaseChartDirective | undefined;
// Pie
public pieChartOptions: ChartConfiguration['options'] = {
responsive: true,
plugins: {
legend: {
display: true,
position: 'bottom',
},
},
};
public pieChartData: ChartData<'pie', number[], string | string[]> = {
labels: ['Web Design', 'App Dev', 'UI Design', 'Graphics'],
datasets: [
{
data: [24, 36, 25, 15],
},
],
};
public pieChartType: ChartType = 'pie';
public pieChartPlugins = [DatalabelsPlugin];
// events
public chartClicked({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
constructor() {}
ngOnInit() {}
}
In the above code, the @ViewChild(BaseChartDirective)
decorator is used to get a reference to the BaseChartDirective
instance, which is a directive used by Chart.js
to interact with the chart canvas. The pieChartOptions
property is used to configure the options for the pie chart. The options include making the chart responsive and displaying the legend at the bottom of the chart.
The pieChartData
property contains the data to be displayed in the pie chart. It consists of an array of labels for each slice of the pie chart and an array of data values for each label. The pieChartType
property is set to pie
to specify that the chart is a pie chart. The pieChartPlugins
property is an array of plugins to be used with the chart. In this case, the DatalabelsPlugin
is used to display the values of each slice of the pie chart. The chartClicked
and chartHovered
methods are used to handle user interaction events on the chart, such as clicking and hovering over a slice of the pie chart.
Next, I will write the template for the pie chart in pie-chart.component.html
in the following way:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Current Semester GPA</ion-card-subtitle>
<ion-card-title>Distribution</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="pieChartData"
[type]="pieChartType"
[options]="pieChartOptions"
[plugins]="pieChartPlugins"
>
</canvas>
</ion-card-content>
</ion-card>
This is an HTML template that includes an Ionic card component and a canvas element that displays a pie chart using Chart.js library. The data for the pie chart is provided by the pieChartData
object in the TypeScript component file, and the chart options and plugins are set using pieChartOptions
and pieChartPlugins
objects respectively. The baseChart
directive is used to initialize and configure the Chart.js library on the canvas element.
The card component has a header with a subtitle and a title, and the canvas element is included in the content section of the card. The [data]
, [type]
, [options]
, and [plugins]
attributes on the canvas element are used to bind the relevant properties of the pie chart component to the canvas element in the template. This allows the component to dynamically update the chart whenever the data changes.
Next, I will simply import the component into the analytics page in the Ts file and HTML file as follows:
import { PieChartComponent } from 'src/app/components/pie-chart/pie-chart.component';
<app-pie-chart></app-pie-chart>
And with this, the Pie chart appears as a card on the analytics page.
Next, I will create a Rradar Chart that will demonstrate the Academic Activity Distribution in Radar Chart: Library, Labs, Lectures, Self Study over Last Sem and Current Sem by first creating a component via ionic generate component components/radar-chart
and begin writing the logic for this in radar-chart.component.ts
file in the following way:
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartConfiguration, ChartData, ChartEvent, ChartType } from 'chart.js';
import { NgChartsModule } from 'ng2-charts';
import DataLabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, CommonModule, FormsModule, NgChartsModule],
selector: 'app-radar-chart',
templateUrl: './radar-chart.component.html',
styleUrls: ['./radar-chart.component.scss'],
})
export class RadarChartComponent implements OnInit {
// Radar
public radarChartOptions: ChartConfiguration['options'] = {
responsive: true,
plugins: {
legend: {
position: 'bottom',
},
},
};
public radarChartLabels: string[] = [
'Lecture',
'Lab',
'Library',
'Studio',
'Workshop',
'Self Study',
'Other',
];
public radarChartData: ChartData<'radar'> = {
labels: this.radarChartLabels,
datasets: [
{ data: [65, 59, 90, 81, 56, 55, 40], label: 'Current Sem' },
{ data: [28, 48, 40, 19, 96, 27, 100], label: 'Last Sem' },
],
};
public radarChartType: ChartType = 'radar';
// events
public chartClicked({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
constructor() {}
ngOnInit() {}
}
This above class displays a radar chart using the Chart.js library. Here's what each part does:
public radarChartOptions
: This is an object that specifies the options for the radar chart, such as whether it should be responsive (i.e., resize automatically to fit the container) and where the legend should be positioned.public radarChartLabels
: This is an array of strings that specifies the labels for each segment of the radar chart.public radarChartData
: This is an object that specifies the data to be displayed in the radar chart. It has two properties:labels
, which is an array of strings that matches theradarChartLabels
array, anddatasets
, which is an array of objects that specify the data for each dataset to be plotted. Each dataset has adata
property that is an array of numbers representing the data points for each segment of the radar chart, and alabel
property that is a string representing the label for that dataset.public radarChartType
: This is a string that specifies the type of chart to be displayed, which in this case is "radar".public chartClicked
andpublic chartHovered
: These are functions that handle events triggered by user interaction with the radar chart. They take an object withevent
andactive
properties, whereevent
is the Chart.js event object andactive
is an array of objects representing the data points that were clicked or hovered over. In this implementation, they simply log the event and active objects to the console.
Next, I will write the template structure in radar-chart.component.html
file in the following way:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Academic Distribution</ion-card-subtitle>
<ion-card-title>Activities</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="radarChartData"
[options]="radarChartOptions"
[type]="radarChartType"
>
</canvas>
</ion-card-content>
</ion-card>
The <ion-card>
element contains an <ion-card-header>
and <ion-card-content>
element for the chart. The <canvas>
element is used to create the chart, with various properties binding to the radarChartData
, radarChartOptions
, and radarChartType
properties of the component.
The radarChartOptions
property defines the options for the chart, including the position of the legend. The radarChartLabels
property defines an array of labels for the different activities.
The radarChartData
property defines an object that contains an array of data points for each dataset in the chart, along with their labels. In this case, there are two datasets representing the current and last semester, with their corresponding data points for each activity.
The radarChartType
property specifies the type of chart to create, in this case, a radar chart.
The chartClicked
and chartHovered
methods handle events for when the chart is clicked or hovered over, respectively.
Now, I will simply import this component in the analytics page’s TS and HTML file like this:
import { RadarChartComponent } from 'src/app/components/radar-chart/radar-chart.component';
<app-radar-chart></app-radar-chart>
And with this, the Radar Chart appears on the analytics page as a separate card.
Next, I will create a Polar Chart (Angular Charts Demo (valor-software.com)) that will demonstrate the Subject Wise Attendance of a student. First, I will create the component using ionic generate component components/polar-area-chart
and write the logic for this in polar-area-chart.component.ts
file like this:
import { NgChartsModule } from 'ng2-charts';
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartData, ChartType, ChartEvent, ChartConfiguration } from 'chart.js';
import DataLabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, FormsModule, CommonModule, NgChartsModule],
selector: 'app-polar-area-chart',
templateUrl: './polar-area-chart.component.html',
styleUrls: ['./polar-area-chart.component.scss'],
})
export class PolarAreaChartComponent implements OnInit {
// PolarArea
public polarAreaChartLabels: string[] = [
'Web Design',
'App Dev',
'UI Design',
'Graphics',
'Overall',
];
public polarAreaChartData: ChartData<'polarArea'> = {
labels: this.polarAreaChartLabels,
datasets: [
{
data: [36, 55, 67, 86, (36 + 55 + 67 + 73) / 4],
label: 'Current Sem',
},
],
};
public polarAreaLegend = true;
//position of legend
public polarAreaChartOptions: ChartConfiguration['options'] = {
responsive: true,
plugins: {
legend: {
position: 'bottom',
},
},
scales: {
r: {
angleLines: {
display: false,
},
suggestedMin: 0,
suggestedMax: 100,
},
},
};
public polarAreaChartType: ChartType = 'polarArea';
// events
public chartClicked({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
constructor() {}
ngOnInit() {}
}
The above code defines a component called PolarAreaChartComponent
. It includes a chart that displays data in a polar area chart format. Here is a breakdown of the code:
public polarAreaChartLabels: string[]
: An array of strings representing the labels of the chart's segments.public polarAreaChartData: ChartData<'polarArea'>
: An object that contains the chart's data and configuration. It includes an array of datasets, which contains an object that specifies the data points and label for the chart. The'polarArea'
type parameter specifies the chart type.public polarAreaLegend = true
: A boolean value indicating whether or not to display the chart's legend.public polarAreaChartOptions: ChartConfiguration['options']
: An object that defines the chart's options, including its plugins and scales. It specifies that the legend should be displayed at the bottom, and thescales
object specifies that ther
scale should have no angle lines, a suggested minimum value of 0, and a suggested maximum value of 100.public polarAreaChartType: ChartType = 'polarArea'
: A string specifying the chart type.public chartClicked
andpublic chartHovered
: Two methods that handle chart events.
Next, I will write the template code in polar-area-chart.html
in the following way:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Subject Wise </ion-card-subtitle>
<ion-card-title>Attendance</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="polarAreaChartData"
[legend]="polarAreaLegend"
[type]="polarAreaChartType"
[options]="polarAreaChartOptions"
>
</canvas>
</ion-card-content>
</ion-card>
The above code creates an Ionic card that contains a chart displaying subject-wise attendance data. The chart is a polar area chart, which shows the percentage of attendance in different subjects. The chart is created using the canvas
element and the baseChart
directive, which is provided by the ng2-charts
library.
The attendance data is provided in the polarAreaChartData
variable, which contains an array of labels for the subjects and an array of attendance percentages for each subject. The polarAreaChartOptions
variable contains the configuration options for the chart, including the position of the legend and the suggested minimum and maximum values for the scale.
Finally, the polarAreaChartType
variable specifies the type of chart to be displayed and the polarAreaLegend
variable controls whether the legend is displayed. These variables are passed as inputs to the canvas
element using property binding.
And now, I will simply import this componet in the analytics page in the TS file and HTML file in the following way:
import { PolarAreaChartComponent } from 'src/app/components/polar-area-chart/polar-area-chart.component';
<app-polar-area-chart></app-polar-area-chart>
And with this the polar area chart is displayed on the analytics page inside a card.
Next, I will create a bar chart to demonstrate Subject Wise Performance by creating a component via ionic generate component components/bar-chart and writing the logic for it in bar-chart.component.ts
file in the following way:
import { BaseChartDirective, NgChartsModule } from 'ng2-charts';
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartConfiguration, ChartType, ChartData, ChartEvent } from 'chart.js';
import DataLabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, FormsModule, CommonModule, NgChartsModule],
selector: 'app-bar-chart',
templateUrl: './bar-chart.component.html',
styleUrls: ['./bar-chart.component.scss'],
})
export class BarChartComponent implements OnInit {
@ViewChild(BaseChartDirective) chart: BaseChartDirective | undefined;
public barChartOptions: ChartConfiguration['options'] = {
responsive: true,
// We use these empty structures as placeholders for dynamic theming.
scales: {
x: {},
y: {
min: 0,
suggestedMax: 100,
},
},
plugins: {
legend: {
display: true,
position: 'bottom',
},
datalabels: {
display: false,
},
},
};
public barChartType: ChartType = 'bar';
public barChartPlugins = [DataLabelsPlugin];
public barChartData: ChartData<'bar'> = {
labels: ['Web Design', 'App Dev', 'UI Design', 'Graphics', 'Overall'],
datasets: [
{ data: [65, 59, 80, 81, (65 + 59 + 80 + 81) / 4], label: 'Last Sem' },
{ data: [28, 48, 40, 19, (28 + 48 + 40 + 19) / 4], label: 'Current Sem' },
],
};
// events
public chartClicked({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
constructor() {}
ngOnInit() {}
}
This is a component for displaying a bar chart in an Angular application using Chart.js library.
The @ViewChild
decorator is used to get access to the chart instance, which can be used to call methods like update()
to update the chart dynamically.
The barChartOptions
object specifies the options for the chart, including responsive design, the scales of the chart (min and max values), and the plugins for the chart. In this case, there is a legend at the bottom and a plugin to display data labels.
The barChartType
specifies the type of chart (in this case, a bar chart) and barChartPlugins
specifies the plugins to use (in this case, DataLabelsPlugin
).
The barChartData
object specifies the data for the chart, including the labels and datasets, with each dataset having its own label and data values.
Finally, there are two event handlers (chartClicked
and chartHovered
) that can be used to perform actions when the chart is clicked or hovered over.
Next, I will write the template for this in bar-chart.component.html
like this:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Subject Wise </ion-card-subtitle>
<ion-card-title>Performance</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="barChartData"
[options]="barChartOptions"
[plugins]="barChartPlugins"
[type]="barChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"
>
</canvas>
</ion-card-content>
</ion-card>
This is a code snippet for displaying a bar chart in an Ionic Card component. The <ion-card>
element defines a card with a header and content section. The content section contains a canvas element that renders the bar chart using the Chart.js library. The baseChart
directive is used to apply the necessary settings for rendering the chart.
The chart data and options are provided by the barChartData
and barChartOptions
properties respectively. The barChartPlugins
property specifies any plugins that should be used for the chart, which in this case includes the Data Labels plugin. The barChartType
property specifies the type of chart to be rendered, which is a bar chart in this case.
The (chartHover)
and (chartClick)
events are used to handle interactions with the chart, which are defined in the chartHovered
and chartClicked
methods respectively.
And now I will simply import this component in the analytics page in TS and HTM file like this:
import { BarChartComponent } from 'src/app/components/bar-chart/bar-chart.component';
<app-bar-chart></app-bar-chart>
And with this, the bar chart will be visible on the analytics page within a card.
Next, I will create a Scatter Plot Chart to demonstrate GPA vs Weekly Study time in Scatter Chart. This could help students understand how their study habits may be impacting their academic performance. I will create the component via ionic generate component components/scatter-chart
and write the logic for this in scatter-chart.component.ts file in the following way:
import { NgChartsModule } from 'ng2-charts';
import { CommonModule } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';
import { ChartConfiguration, ChartData, ChartEvent, ChartType } from 'chart.js';
import DataLabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, CommonModule, FormsModule, NgChartsModule],
selector: 'app-scatter-chart',
templateUrl: './scatter-chart.component.html',
styleUrls: ['./scatter-chart.component.scss'],
})
export class ScatterChartComponent implements OnInit {
// scatter
public scatterChartOptions: ChartConfiguration['options'] = {
// ChartConfiguration is a type from chart.js
responsive: true, // make the chart responsive
scales: {
// define the scales of the chart
x: {
type: 'linear', // define the type of scale for the x-axis
position: 'bottom', // define the position of the x-axis
suggestedMax: 50, // define the maximum value of the x-axis
suggestedMin: 0, // define the minimum value of the x-axis
},
y: {
// define the y-axis
min: 0, // define the minimum value of the y-axis
max: 4, // define the maximum value of the y-axis
suggestedMax: 4, // define the suggested maximum value of the y-axis
},
},
plugins: {
// define the plugins of the chart
datalabels: {
// define the datalabels plugin
anchor: 'end', // define the anchor of the datalabels
align: 'end', // define the alignment of the datalabels
},
legend: {
// define the legend of the chart
display: true, // display the legend
position: 'bottom', // define the position of the legend
},
},
};
public scatterChartData: ChartData<'scatter'> = {
// define the data of the chart (the data is an array of objects)
// labels: this.scatterChartLabels,
datasets: [
// define the datasets of the chart
{
data: [
// define the data of the first dataset
{ x: 10, y: 1.2 }, // define the data points of the first dataset
{ x: 25, y: 2.1 },
{ x: 35, y: 2.8 },
{ x: 15, y: 1.8 },
{ x: 45, y: 3.2 },
{ x: 5, y: 1.0 },
{ x: 30, y: 2.7 },
{ x: 20, y: 2.2 },
],
label: 'Current Sem', // define the label of the first dataset
pointRadius: 5, // define the radius of the points of the first dataset
},
{
data: [
{ x: 25, y: 2.5 },
{ x: 35, y: 3.0 },
{ x: 10, y: 2.1 },
{ x: 40, y: 3.5 },
{ x: 15, y: 1.5 },
{ x: 3, y: 0.6 },
{ x: 20, y: 1.8 },
{ x: 45, y: 3.7 },
],
label: 'Last Sem',
pointRadius: 5,
},
],
};
public scatterChartType: ChartType = 'scatter'; // define the type of the chart (scatter)
// events
public chartClicked({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event: ChartEvent;
active: {}[];
}): void {
// console.log(event, active);
}
constructor() {}
ngOnInit() {}
}
This is a TypeScript code for a Scatter Chart Component, which is using Chart.js library for displaying a scatter chart. The code defines the options, data, and type of the scatter chart, and also provides event handlers for when the chart is clicked or hovered over.
The code begins by defining a class called ScatterChartComponent
that implements the OnInit
interface. Inside this class, there are several properties defined.
Firstly, the scatterChartOptions
property defines the options for the scatter chart. These options include the chart's responsiveness, the scales (x and y), and plugins (datalabels and legend) that will be used to customize the appearance of the chart.
Secondly, the scatterChartData
property defines the data that will be displayed on the chart. The data is an array of objects that represent the data points for the chart. Each data point has an x and y value that will be plotted on the chart, and also a label that describes the data point.
The scatterChartType
property defines the type of the chart, which is a scatter chart in this case.
Lastly, there are two event handlers defined for the chart - chartClicked
and chartHovered
- that log to the console when the chart is clicked or hovered over, respectively.
Next, I will write the template code for this in scatter-chart.component.html file in the following way:
<ion-card>
<ion-card-header>
<ion-card-subtitle>GPA vs Weekly Study Time</ion-card-subtitle>
<ion-card-title>Efficiency</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
baseChart
class="chart"
[data]="scatterChartData"
[options]="scatterChartOptions"
[type]="scatterChartType"
>
</canvas>
</ion-card-content>
</ion-card>
This is code for an Ionic card that displays a scatter chart using Chart.js library. The scatter chart represents the relationship between a student's GPA and their weekly study time for achieving that GPA.
The ion-card
element creates a card container for the chart. Within the card, there is an ion-card-header
element which contains a subtitle "GPA vs Weekly Study Time" and a title "Efficiency". The ion-card-content
element contains a canvas
element with [data]
, [options]
, and [type]
attributes that are bound to variables defined in the corresponding TypeScript file.
The scatterChartData
variable defines the data for the chart. It is an object with a datasets
array containing two datasets representing the current and last semesters. Each dataset has an array of objects representing the data points on the chart with x and y coordinates. The scatterChartOptions
variable defines various chart options, including the scales and plugins, and the scatterChartType
variable defines the type of chart, which is set to "scatter".
And now, I will simply import this component into the analytics page’s TS and HTMl file:
import { ScatterChartComponent } from 'src/app/components/scatter-chart/scatter-chart.component';
<app-scatter-chart></app-scatter-chart>
And this will display the scatter chart on the analytics page.
Next, I will create a dynamic chart which will switch between a bar chart and a line chart and will display comparative module grades for different assignments. I will create the component via ionic generate component components/dynamic-chart
and write the logic for this in dynamic-chart.component.ts
file in the following way:
import { FormsModule } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { Component, OnInit, ViewChild } from '@angular/core';
import { IonicModule } from '@ionic/angular';
import { BaseChartDirective, NgChartsModule } from 'ng2-charts';
import { ChartConfiguration, ChartData, ChartEvent, ChartType } from 'chart.js';
import DataLabelsPlugin from 'chartjs-plugin-datalabels';
@Component({
standalone: true,
imports: [IonicModule, CommonModule, FormsModule, NgChartsModule],
selector: 'app-dynamic-chart',
templateUrl: './dynamic-chart.component.html',
styleUrls: ['./dynamic-chart.component.scss'],
})
export class DynamicChartComponent implements OnInit {
@ViewChild(BaseChartDirective) chart: BaseChartDirective | undefined; // this is the #chart reference in the html file for the chart component
public barChartOptions: ChartConfiguration['options'] = {
elements: {
line: {
tension: 0.4,
},
},
// We use these empty structures as placeholders for dynamic theming.
scales: {
x: {},
y: {
min: 0,
max: 100,
// suggestedMax: 100,
beginAtZero: true,
ticks: {
stepSize: 5,
},
},
},
plugins: {
legend: { display: true, position: 'bottom' },
},
};
public barChartLabels: string[] = [
'Week 1',
'Week 2',
'Week 3',
'Week 4',
'Week 5',
];
public barChartType: ChartType = 'bar';
public barChartData: ChartData<'bar'> = {
labels: this.barChartLabels,
datasets: [
{ data: [65, 59, 80, 81, 56], label: 'Web Design' },
{ data: [28, 48, 40, 19, 86], label: 'App Dev' },
{ data: [35, 67, 89, 15, 20], label: 'UI Design' },
{ data: [15, 95, 45, 63, 32], label: 'Graphics' },
],
};
// events
public chartClicked({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
public chartHovered({
event,
active,
}: {
event?: ChartEvent;
active?: {}[];
}): void {
// console.log(event, active);
}
public async randomize(): Promise<void> {
this.barChartType = this.barChartType === 'bar' ? 'line' : 'bar';
}
constructor() {}
ngOnInit() {
this.randomize();
}
}
This is a TypeScript file that defines the DynamicChartComponent class, which is used to create a dynamic chart component in a web application.
The component contains a bar chart that displays data for four categories over the course of five weeks. The chart can be toggled between a bar chart and a line chart, and it has options for dynamic theming.
The class has several properties, including:
chart
: This is a reference to the chart component in the HTML file.barChartOptions
: This is an object that contains options for the bar chart, such as the tension of the line and the position of the legend.barChartLabels
: This is an array of strings that represents the labels for the x-axis of the bar chart.barChartType
: This is a string that represents the type of chart being used (either 'bar' or 'line').barChartData
: This is an object that contains the data to be displayed in the chart. It includes an array of labels and an array of datasets, each with its own set of data.
The class also has several methods:
chartClicked
andchartHovered
: These methods are called when the user clicks or hovers over the chart.randomize
: This method toggles the type of chart being used.
Finally, the ngOnInit
method is called when the component is initialized. In this case, it calls the randomize
method to set the chart to a random type (either bar or line) when the component is first loaded.
Next, I will write the template for this in dynamic-chart.component.html
file in the following way:
<ion-card>
<ion-card-header>
<ion-card-subtitle>Module Comparison</ion-card-subtitle>
<ion-card-title>Grades</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas
class="chart"
baseChart
[data]="barChartData"
[options]="barChartOptions"
[type]="barChartType"
(chartHover)="chartHovered($event)"
(chartClick)="chartClicked($event)"
>
</canvas>
<ion-button color="secondary" fill="solid" (click)="randomize()">
{{ barChartType === "bar" ? "Line" : "Bar" }} Chart
</ion-button>
</ion-card-content>
</ion-card>
This is an Ionic component that displays a chart within an ion-card
container. The chart is created using the canvas
element with the baseChart
attribute, which indicates that the chart is built using a chart library, such as Chart.js.
The data
and options
attributes of the canvas
element are bound to properties of the component's class. barChartData
, barChartOptions
, and barChartType
properties define the data, options, and type of the chart respectively.
The (chartHover)
and (chartClick)
events of the canvas
element are bound to the chartHovered()
and chartClicked()
methods of the component's class.
The ion-button
component is used to change the type of the chart, from bar to line and vice versa, by calling the randomize()
method of the component's class when clicked.
The ion-card
element is used to provide a header and a title for the chart, making it a more informative and organized UI element.
And now, I will simply import the component in the analytics page‘s TS and HTML file:
import { DynamicChartComponent } from 'src/app/components/dynamic-chart/dynamic-chart.component';
<app-dynamic-chart></app-dynamic-chart>
And with this, the dynamic chart appears on the analytics page.
The analytics page is demonstrated in figures 90, 91, 92, and 93 below:
Figure 90: Line & Pie Chart |
Figure 91: Radar Chart |
Figure 92: Polar Area & Bar Chart |
Figure 93: Scatter Plot & Dynamic Chart |
Conclusion
In this twenty-third installment of our series on building a multiplatform application with Angular-15 and Ionic-7, we explored the creation of interactive charts to visualize numerical data using the Charts JS library. By incorporating this powerful library into our Angular-15 Ionic-7 app, we empowered users to gain insights and analyze data effectively through dynamic and interactive charts.
Visualizing numerical data is crucial for understanding patterns, trends, and relationships within datasets. With the Charts JS library, we seamlessly integrated a wide range of chart types, including bar charts, line charts, pie charts, and more, providing users with versatile options for data representation.
Throughout this tutorial, we guided you through the process of integrating the Charts JS library into your app and configuring it to suit your needs. We explored the various chart types available and demonstrated how to populate them with numerical data, customize their appearance, and enable interactive features.
By following best practices for data visualization, chart configuration, and user interaction, you now have the knowledge and tools to create visually appealing and informative charts within your Angular-15 Ionic-7 app.
We hope this tutorial has provided you with valuable insights and practical techniques for visualizing numerical data using the Charts JS library. By leveraging the power of data visualization, you can enhance the data analysis capabilities of your application and enable users to make informed decisions based on the insights gained from the charts.
Thank you for joining us on this journey as we explored the fascinating world of app development with Angular-15, Ionic-7, and the Charts JS library. Stay tuned for future installments where we will continue to explore new features and functionalities to make our app even more powerful, dynamic, and user-friendly.
Happy coding!