Adding charts to an Ionic project

May 30, 2017, 11:26 am Categories:

Categories

One of the great things about developing with Ionic is the range of third-party plugins and packages that can be integrated with the framework to implement different types of functionality.

Case in point: generating charts and graphs.

Let's be honest here, raw data isn't the most exciting of content to work with (unless of course you happen to be a data-mining analyst who gets off on that stuff - but we're not going to dwell there) and as human beings we tend to be heavily visually biased. We like the combination of colour, shape, layout, typography and imagery to communicate content whether that be in the form of ideas, topics, themes or messages (internet memes anyone?)

As designers and developers part of our job is to not only deliver that content but also find ways to make that more engaging for the end user. Not always an easy task when working with bland looking datasets and statistics right?

Enter ChartJS - an open source library that allows developers to render data in any of the following chart types:

  • Line
  • Bar
  • Radar
  • Doughnut
  • Pie
  • Polar Area
  • Bubble
  • Scatter
  • Area
  • Mixed

In addition to the wide range of available charts the online documentation that accompanies the software (particularly the configuration options available globally and per chart type) is also quite impressive, not to mention helpful.

Using this library I'm going to take you through developing a single page Ionic application that provides a daily breakdown of my typical technology usage and digital related tasks using the following charts:

  • Bar
  • Line
  • Pie

By the end of the tutorial you should see the following application being rendered to your system browser:

ChartJS types displayed in an Ionic project

Ready to get started?

Let's go!

Laying the foundation

Select a location on your computer where you would normally store your digital projects and create a new Ionic project named ionic-charts that uses a blank template with the following command:

ionic start ionic-charts blank

Sit back and relax for a few minutes as this might take a while to complete.

Once the project has been generated you'll then need to install the ChartJS package using npm:

npm install chart.js --save

With that node package added to the project we now have everything we need to start developing our application.

First steps

Let's begin by fleshing out the basic skeleton for the application's logic in the ionic-charts/src/pages/home/home.ts file with the following code:

import { Component, ViewChild } from '@angular/core';
import { IonicPage, 
         NavController,
         NavParams } from 'ionic-angular';

import { Chart } from 'chart.js';


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
   @ViewChild('pieChart') pieChart;
   @ViewChild('barChart') barChart;
   @ViewChild('lineChart') lineChart;


   public technologies              : any = {
   										        "technologies" : [
                                                  {
                                                     'technology' : 'Mobile: Ionic/Angular',
                                                     'time'       : 50,
                                                     'color'      : 'rgba(206, 61, 95, 0.5)',
                                                     'hover'      : 'rgba(199, 108, 129, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Front-end: Sass/CSS',
                                                     'time'       : 15,
                                                     'color'      : 'rgba(83, 131, 185, 0.5)',
                                                     'hover'      : 'rgba(122, 160, 202, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Server: PHP/MySQL',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(198, 147, 194, 0.5)',
                                                     'hover'      : 'rgba(200, 166, 197, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Code Documentation',
                                                     'time'       : 5,
                                                     'color'      : 'rgba(54, 116, 152, 0.5)',
                                                     'hover'      : 'rgba(103, 139, 160, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Knowledge: Blogging',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(152, 54, 145, 0.5)',
                                                     'hover'      : 'rgba(152, 89, 149, 0.5)',
                                                  },
                                                  {
                                                     'technology' : 'SEO/Online Marketing',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(192, 192, 192, 0.5)',
                                                     'hover'      : 'rgba(220, 220, 220, 0.5)'
                                                  }
   										       ]
   										    };		
   public pieChartEl                : any;
   public barChartEl                : any;
   public lineChartEl               : any;
   public chartLabels               : any    = [];
   public chartValues               : any    = [];
   public chartColours              : any    = [];
   public chartHoverColours         : any    = [];
   public chartLoadingEl            : any;


   constructor( public navCtrl      : NavController, 
                public navParams    : NavParams) 
   { }




   ionViewDidLoad() 
   {
      this.defineChartData();
      this.createPieChart();  
      this.createBarChart();  
      this.createLineChart();   
   }



   /**
    *
    * Parse the JSON data, push specific keys into selected arrays for use with 
    * each chart
    *
    */
   defineChartData() : void
   {
      let k : any;

      for(k in this.technologies.technologies)
      {
         var tech  =      this.technologies.technologies[k];

         this.chartLabels.push(tech.technology);
         this.chartValues.push(tech.time);
         this.chartColours.push(tech.color);
         this.chartHoverColours.push(tech.hover);
      }
   }




   /**
    *
    * Configure the Pie chart, define configuration options
    *
    */
   createPieChart() : void
   {
      // We'll define the pie chart related logic here shortly
   }




   /**
    *
    * Configure the Bar chart, define configuration options
    *
    */
   createBarChart() : void
   {
      // We'll define the pie chart related logic here shortly
   }




   /**
    *
    * Configure the Line chart, define configuration options
    *
    */
   createLineChart() : void
   {
      // We'll define the pie chart related logic here shortly
   }



}

We start by importing the ViewChild Angular module so we can programmatically interact with and access the HTML elements in our page template where the charts will be situated, as well importing the Chart module from our recently installed chart.js library.

Within the HomePage class we begin by using the @ViewChild annotation to programmatically access each individual chart element in our HTML template (we'll code the markup for the application towards the end of this tutorial):

@ViewChild('pieChart') pieChart;
@ViewChild('barChart') barChart;
@ViewChild('lineChart') lineChart;

This is then followed by defining the data that will be used for each chart in the technologies array; consisting of the item key, item value, the colour for that item when rendered as an individual segment on the chart and what colour that chart segment will be displayed as when hovered over/activated by the user:

public technologies              : any = {
   "technologies" : [
      {
         'technology' : 'Mobile: Ionic/Angular',
         'time'       : 50,
         'color'      : 'rgba(206, 61, 95, 0.5)',
         'hover'      : 'rgba(199, 108, 129, 0.5)'
      },
      {
         'technology' : 'Front-end: Sass/CSS',
         'time'       : 15,
         'color'      : 'rgba(83, 131, 185, 0.5)',
         'hover'      : 'rgba(122, 160, 202, 0.5)'
      },
      {
         'technology' : 'Server: PHP/MySQL',
         'time'       : 10,
         'color'      : 'rgba(198, 147, 194, 0.5)',
         'hover'      : 'rgba(200, 166, 197, 0.5)'
      },
      {
         'technology' : 'Code Documentation',
         'time'       : 5,
         'color'      : 'rgba(54, 116, 152, 0.5)',
         'hover'      : 'rgba(103, 139, 160, 0.5)'
      },
      {
         'technology' : 'Knowledge: Blogging',
         'time'       : 10,
         'color'      : 'rgba(152, 54, 145, 0.5)',
         'hover'      : 'rgba(152, 89, 149, 0.5)',
      },
      {
         'technology' : 'SEO/Online Marketing',
         'time'       : 10,
         'color'      : 'rgba(192, 192, 192, 0.5)',
         'hover'      : 'rgba(220, 220, 220, 0.5)'
      }
   ]
};		

We then define the remaining public properties; the first three of which will be used as references to the individual chart types with the remaining properties used to store the data for each key/value pair from the technologies array that was defined previously:

public pieChartEl                : any;
public barChartEl                : any;
public lineChartEl               : any;
public chartLabels               : any    = [];
public chartValues               : any    = [];
public chartColours              : any    = [];
public chartHoverColours         : any    = [];

Within the ionViewDidLoad lifecycle event the following methods are called as soon as the page view has completed loading:

  • defineChartData - Parses the data from the technologies array, pushing the value for each key into a specific array
  • createPieChart - Configures/generates a pie chart for the application
  • createBarChart - Configures/generates a bar chart for the application
  • createLineChart - Configures/generates a line chart for the application

The defineChartData method simply loops through the technologies array and pushes the value for each key into its own array (which will be subsequently used within each chart method when configuring the data/structure and format of that specific chart):

defineChartData()
{
   let k : any;

   for(k in this.technologies.technologies)
   {
      var tech  =      this.technologies.technologies[k];

      this.chartLabels.push(tech.technology);
      this.chartValues.push(tech.time);
      this.chartColours.push(tech.color);
      this.chartHoverColours.push(tech.hover);
   }
}

With the basic skeleton of the class now in place we can turn our attention to implementing the code for each chart type.

I'm not going to spend time going over every single configuration option in-depth - these can be viewed here - but I will concentrate on the most important aspects that you need to be aware of for each chart.

Before we do this though you need to understand that every chart that is generated follows the same basic format:

  • The HTML element where the chart will be assigned
  • The configuration options for the chart (data, axes, legend etc)

Let's look at how this is implemented for each of the chart types beginning with the bar chart.

Creating the bar chart

The createBarChart method implements the following configuration:

/**
 *
 * Configure the Bar chart, define configuration options
 *
 */
createBarChart()
{
   this.barChartEl 	          = new Chart(this.barChart.nativeElement, 
   {
      type: 'bar',
      data: {
         labels: this.chartLabels,
         datasets: [{
            label                 : 'Daily Technology usage',
            data                  : this.chartValues,
            duration              : 2000,
            easing                : 'easeInQuart',
            backgroundColor       : this.chartColours,
            hoverBackgroundColor  : this.chartHoverColours
         }]
      },
      options : {
         maintainAspectRatio: false,
         legend         : {
            display     : true,
            boxWidth    : 80,
            fontSize    : 15,
            padding     : 0
         },
         scales: {
            yAxes: [{
               ticks: {
                  beginAtZero:true,
                  stepSize: 5,
                  max : 100
               }
            }],
            xAxes: [{
               ticks: {
                  autoSkip: false
               }
            }]
         }
      }
   });
}

As you can see a chart configuration is created from a simple JSON object consisting of different key/value pair combinations.

To define the chart type we use the following:

type: 'bar',

The data that we want to supply for the chart is configured, with supplementary options, through the data object like so:

data: {
   labels: this.chartLabels,
   datasets: [{
      label                 : 'Daily Technology usage',
      data                  : this.chartValues,
      duration              : 2000,
      easing                : 'easeInQuart',
      backgroundColor       : this.chartColours,
      hoverBackgroundColor  : this.chartHoverColours
   }]
}

Notice that the individual arrays that we used to separate out the values for each key in the technologies array are used in the following configuration options for the above:

  • labels - Displayed over each chart segment when that segment is activated by the user
  • data - The data used to render each chart segment
  • backgroundColor - The colour for each chart segment
  • hoverBackgroundColor - The colour for each chart segment when that segment is hovered over/activated by the user

We subsequently use the options key to define different aspects of the chart such as how the X and Y axes are to be configured along with the chart legend:

options : {
   maintainAspectRatio: false,
   legend         : {
      display     : true,
      boxWidth    : 80,
      fontSize    : 15,
      padding     : 0
   },
   scales: {
      yAxes: [{
         ticks: {
            beginAtZero:true,
            stepSize: 5,
            max : 100
         }
      }],
      xAxes: [{
         ticks: {
            autoSkip: false
         }
      }]
   }
}

Creating the pie chart

The pie chart configuration follows a similar format as the previous chart with a few key differences:

  • type is set to pie
  • Sets an animation property of 5 seconds to animate the chart and each of its segments into view
  • The chart legend is rendered to the canvas through the chartJS generateLegend method
/**
 *
 * Configure the Pie chart, define configuration options
 *
 */
createPieChart()
{
      
   this.pieChartEl 				= 	new Chart(this.pieChart.nativeElement, 
   {
      type: 'pie',
      data: {
         labels: this.chartLabels,
         datasets: [{
            label                 : 'Daily Technology usage',
            data                  : this.chartValues,
            duration              : 2000,
            easing                : 'easeInQuart',
            backgroundColor       : this.chartColours,
            hoverBackgroundColor  : this.chartHoverColours
         }]
      },
      options : {
         maintainAspectRatio: false,
         layout: {
            padding: {
               left     : 50,
               right    : 0,
               top      : 0,
               bottom   : 0
            }
         },
         animation: {
            duration : 5000
         }
      }
   });

   this.chartLoading = this.pieChartEl.generateLegend();
}

Creating the line chart

The line chart follows a similar configuration to that of the bar chart with a few key differences:

  • type is set to line
  • Within the datasets key we set an option of fill to false to prevent the area under the line being assigned a background colour
/**
 *
 * Configure the Line chart, define configuration options
 *
 */
createLineChart()
{
   this.lineChartEl 		  = new Chart(this.lineChart.nativeElement, 
   {
      type: 'line',
      data: {
         labels: this.chartLabels,
         datasets: [{
            label                 : 'Daily Technology usage',
            data                  : this.chartValues,
            duration              : 2000,
            easing                : 'easeInQuart',
            backgroundColor       : this.chartColours,
            hoverBackgroundColor  : this.chartHoverColours,
            fill 				   : false
         }]
      },
      options : {
         maintainAspectRatio: false,
         legend         : {
            display     : true,
            boxWidth    : 80,
            fontSize    : 15,
            padding     : 0
         },
         scales: {
            yAxes: [{
               ticks: {
                  beginAtZero:true,
                  stepSize: 5,
                  max : 100
               }
            }],
            xAxes: [{
               ticks: {
                  autoSkip: false
               }
            }]
         }
      }
   });
}

With that configuration we now complete the coding for the logic of the charts used in the application.

Chart logic in full

import { Component, ViewChild } from '@angular/core';
import { AlertController, 
         IonicPage, 
         NavController,
         NavParams, 
         Platform } from 'ionic-angular';

import { Chart } from 'chart.js';


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {
   @ViewChild('pieChart') pieChart;
   @ViewChild('barChart') barChart;
   @ViewChild('lineChart') lineChart;


   public technologies              : any = {
   										        "technologies" : [
                                                  {
                                                     'technology' : 'Mobile: Ionic/Angular',
                                                     'time'       : 50,
                                                     'color'      : 'rgba(206, 61, 95, 0.5)',
                                                     'hover'      : 'rgba(199, 108, 129, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Front-end: Sass/CSS',
                                                     'time'       : 15,
                                                     'color'      : 'rgba(83, 131, 185, 0.5)',
                                                     'hover'      : 'rgba(122, 160, 202, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Server: PHP/MySQL',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(198, 147, 194, 0.5)',
                                                     'hover'      : 'rgba(200, 166, 197, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Code Documentation',
                                                     'time'       : 5,
                                                     'color'      : 'rgba(54, 116, 152, 0.5)',
                                                     'hover'      : 'rgba(103, 139, 160, 0.5)'
                                                  },
                                                  {
                                                     'technology' : 'Knowledge: Blogging',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(152, 54, 145, 0.5)',
                                                     'hover'      : 'rgba(152, 89, 149, 0.5)',
                                                  },
                                                  {
                                                     'technology' : 'SEO/Online Marketing',
                                                     'time'       : 10,
                                                     'color'      : 'rgba(192, 192, 192, 0.5)',
                                                     'hover'      : 'rgba(220, 220, 220, 0.5)'
                                                  }
   										       ]
   										    };		
   public pieChartEl                : any;
   public barChartEl                : any;
   public lineChartEl               : any;
   public chartLabels               : any    = [];
   public chartValues               : any    = [];
   public chartColours              : any    = [];
   public chartHoverColours         : any    = [];


   constructor( public navCtrl      : NavController, 
                public navParams    : NavParams) 
   { }




   ionViewDidLoad() 
   {
      this.defineChartData();
      this.createPieChart();  
      this.createBarChart();  
      this.createLineChart();   
   }




   /**
    *
    * Parse the JSON data, push specific keys into selected arrays for use with 
    * each chart
    *
    */
   defineChartData()
   {
      let k : any;

      for(k in this.technologies.technologies)
      {
         var tech  =      this.technologies.technologies[k];

         this.chartLabels.push(tech.technology);
         this.chartValues.push(tech.time);
         this.chartColours.push(tech.color);
         this.chartHoverColours.push(tech.hover);
      }
   }




   /**
    *
    * Configure the Pie chart, define configuration options
    *
    */
   createPieChart()
   {
      
      this.pieChartEl 			= new Chart(this.pieChart.nativeElement, 
      {
         type: 'pie',
         data: {
             labels: this.chartLabels,
             datasets: [{
                 label                 : 'Daily Technology usage',
                 data                  : this.chartValues,
                 duration              : 2000,
                 easing                : 'easeInQuart',
                 backgroundColor       : this.chartColours,
                 hoverBackgroundColor  : this.chartHoverColours
             }]
         },
         options : {
            maintainAspectRatio: false,            
            layout: {
               padding: {
                  left     : 50,
                  right    : 0,
                  top      : 0,
                  bottom   : 0
               }
            },
            animation: {
               duration : 5000
            }
         }
      });



      this.chartLoading = this.pieChartEl.generateLegend();
   }




   /**
    *
    * Configure the Bar chart, define configuration options
    *
    */
   createBarChart()
   {
      this.barChartEl 			= new Chart(this.barChart.nativeElement, 
      {
         type: 'bar',
         data: {
            labels: this.chartLabels,
             datasets: [{
                 label                 : 'Daily Technology usage',
                 data                  : this.chartValues,
                 duration              : 2000,
                 easing                : 'easeInQuart',
                 backgroundColor       : this.chartColours,
                 hoverBackgroundColor  : this.chartHoverColours
             }]
         },
         options : {
            maintainAspectRatio: false,
            legend         : {
               display     : true,
               boxWidth    : 80,
               fontSize    : 15,
               padding     : 0
            },
            scales: {
                yAxes: [{
                    ticks: {
                       beginAtZero:true,
                       stepSize: 5,
                       max : 100
                    }
                }],
                xAxes: [{
                    ticks: {
                       autoSkip: false
                    }
                }]
            }
         }
      });
   }




   /**
    *
    * Configure the Line chart, define configuration options
    *
    */
   createLineChart()
   {
      this.lineChartEl 			= new Chart(this.lineChart.nativeElement, 
      {
         type: 'line',
         data: {
            labels: this.chartLabels,
             datasets: [{
                 label                 : 'Daily Technology usage',
                 data                  : this.chartValues,
                 duration              : 2000,
                 easing                : 'easeInQuart',
                 backgroundColor       : this.chartColours,
                 hoverBackgroundColor  : this.chartHoverColours,
 				 fill 				   : false
             }]
         },
         options : {
            maintainAspectRatio: false,
            legend         : {
               display     : true,
               boxWidth    : 80,
               fontSize    : 15,
               padding     : 0
            },
            scales: {
                yAxes: [{
                    ticks: {
                       beginAtZero:true,
                       stepSize: 5,
                       max : 100
                    }
                }],
                xAxes: [{
                    ticks: {
                       autoSkip: false
                    }
                }]
            }
         }
      });
   }



}

All that remains now is to define the necessary HTML for the page.

Rendering the template

Thankfully the HTML for rendering our predefined charts is fairly simple consisting of 3 individual HTML canvas tags (one for each chart type) that implement template reference variables to allow Angular to hook into the template HTML.

Inside the the ionic-charts/src/pages/home/home.html file enter the following mark-up:

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Charts
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  
   <section class="chart-wrapper">
      <canvas #barChart></canvas>
   </section>

  
   <section class="chart-wrapper">
      <canvas #pieChart></canvas>
   </section>
  

   <section class="chart-wrapper">
      <canvas #lineChart></canvas>
   </section>

</ion-content>

Pretty simple right?

With the logic and the templating in place the final task is to provide some simple Sass rules to help define the format and layout of the canvas elements.

In the ionic-charts/src/pages/home/home.scss file enter the following style rules:

page-home {

   .chart-wrapper {
      width: 25%;
      display: inline-block;
      margin: 1em 2em;
   }


   canvas  {
      height: 500px;
   }

}

Although fairly minimal these rules ensure that the canvas tags are spaced equidistantly and have sufficient height to allow the charts to be rendered clearly.

Now that the logic, templating and styling are in place all that remains is to run the application in your system browser with the following command:

ionic serve

All things being well you should be greeted with the following sight:

ChartJS types displayed in an Ionic project

Congratulations! Thanks to ChartJS and its API you've successfully generated bar, pie and lines charts for your application.

In Summary

As you can no doubt appreciate from this tutorial adding charts and graphs to an Ionic application is fairly simple with ChartJS - an extensive API, multiple chart types and in-depth online documentation allow developers to quickly and easily get to grips with the library.

For rendering data into beautiful, visually engaging charts and graphs there's a lot to like about this library.

If I have one gripe about ChartJS though it's this: formatting the legend is not so straightforward - despite the documentation and different configuration options in fact it's more challenging than it really should be, particularly when it comes to aligning each key item.

That said though it's a great library, packed full of charting types and options with extensive online documentation, for any developer looking to add charting functionality to their Ionic applications.

Tags

Categories

Post a comment

All comments are welcome and the rules are simple - be nice and do NOT engage in trolling, spamming, abusiveness or illegal behaviour. If you fail to observe these rules you will be permanently banned from being able to comment.

Top