Charts avec Angular 9

10/02/20 danny


Nous allons créer nos premiers charts avec Angular CLI et Typescript.

Nous utiliserons la librairie Chart.js dans notre prototype Bootstrap.

Nous intégrerons la librairie Chart.js dans notre projet Angular.


Ce que nous allons faire

  • Avant de Commencer
    Quelles sont les librairies Charts en javascript disponibles ?
     
  • Création de notre projet Angular
    Nous utiliserons un projet existant contenant les fonctionnalités essentielles.
    Le projet a été généré avec Angular CLI.
    Il utilise le Routing et le Lazy Loading.
    Il intègre le Framework CSS Bootstrap.
     
  • Prototype bootstrap
    Comment intégrer Chart.js dans nos pages bootstrap.
     
  • Intégration dans notre projet angular
    Comment Intégrer chart.js dans notre projet
     
  • Effectuer les Tests
    Unitaires et end to end.
     
  • Code source
    Le code complet du projet sur github.

Les librairies javascript Charts

Un rapide tour d'horizon des librairies Charts en javascript nous permet d'établir cette liste non exhaustive
Elles sont classées par nombre de stars sur Github (ordre décroissant)

Certaines d'entre elles sont open-source et peuvent être utilisées dans tous les projets commerciaux ou non.

Arbitrairement dans ce tutoriel nous allons utiliser Chart.js


Création du projet Angular

Pour pouvoir continuer ce tutoriel nous devons bien evidemment disposer de certains éléments

  • Node.js : La plateforme javascript
  • Git : Le logiciel de gestion de versions. 
  • Angular CLI : L'outil fourni par Angular.
  • Visual Studio code : Un éditeur de code.

Vous pouvez consulter le tutoriel suivant qui vous explique en détails comment faire


Nous allons utiliser un projet existant dont les caractéristiques sont

  • Genéré avec Angular CLI
  • Gestion du Routing
  • Gestion du Lazy loading
  • Utilisation du Framework CSS Bootstrap
# Créez un répertoire demo (le nom est ici arbitraire)
mkdir demo

# Allez dans ce répertoire
cd demo

# Récupérez le code source sur votre poste de travail
git clone https://github.com/ganatan/angular-example-bootstrap.git

# Allez dans le répertoire qui a été créé
cd angular-example-bootstrap

# Exécutez l'installation des dépendances (ou librairies)
npm install

# Exécutez le programme
npm run start

# Vérifiez son fonctionnement en lançant dans votre navigateur la commande
http://localhost:4200/

Notre prototype contient la partie graphique finale.
Pour avoir plus de détails vous pouvez consulter le tutoriel sur Angular et Bootstrap

Prototype avec Bootstrap et Angular


Chart.js


Avant de l'intégrer dans notre application Angular passons par une étape intérmédiaire plus simple.
Notre prototype Bootstrap se trouve dans le répertoire UI.

Nous allons créer un fichier chartjs.html à partir de home.html.

Le site officiel https://www.chartjs.org/
Et la documentation https://www.chartjs.org/docs/latest/

Les fichiers à télécharger sur notre prototype sont accessibles ici
https://cdnjs.com/libraries/Chart.js

Les 2 fichiers que nous utiliserons seront notamment

  • https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css
  • https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js

Ci-dessous le résultat graphique et le fichier du prototype.
 

ui/chartjs.html
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <title>angular-starter</title>
  <link href="assets/fontawesome/css/all.min.css" rel="stylesheet">
  <link href="assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
  <link href="assets/params/css/index.css" rel="stylesheet">
  <link href="assets/params/css/home.css" rel="stylesheet">

  <link href="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.css" rel="stylesheet">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>

</head>

<body>

  <div class="app">

    <header>
      <nav class="navbar navbar-expand-md fixed-top navbar-dark" style="background-color: #212121;">
        <a class="navbar-brand" href="#">
          <span class="mr-1" style="color:white">ganatan</span>
          <img src="./assets/params/images/logo/ganatan.png" width="20" height="20" alt="">
        </a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarsExampleDefault"
          aria-controls="navbarsExampleDefault" aria-expanded="false" aria-label="Toggle navigation">
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarsExampleDefault">
          <ul class="navbar-nav ml-auto">
            <li class="nav-item active">
              <a class="nav-link" href="#">
                <i class="fas fa-home mr-1"></i>home
              </a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="#">
                <i class="far fa-question-circle mr-1"></i>About
              </a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="#">
                <i class="fas fa-envelope mr-1"></i>Contact
              </a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="#">
                <i class="fas fa-user mr-1"></i>Sign in
              </a>
            </li>
            <li class="nav-item active">
              <a class="nav-link" href="https://github.com/ganatan">
                <i class="fab fa-github mr-1"></i>Github
              </a>
            </li>
          </ul>
        </div>
      </nav>
    </header>



    <main>
      <div class="container-fluid">

        <div class="row pt-1 mb-2">
          <div class="col-md-3 text-center mb-2">
            <canvas id="myChart" width="400" height="400"></canvas>
          </div>
        </div>

      </div>
    </main>

    <div class="footer">
      <div class="container">
        <div class="row">
          <div class="col-12">
            <p class="text-center text-white">&copy; 2019 - www.ganatan.com</p>
          </div>
        </div>
      </div>
    </div>

  </div>

  <script src="assets/jquery/js/jquery-3.4.1.min.js"></script>
  <script src="assets/bootstrap/js/bootstrap.min.js"></script>
  <script src="assets/params/js/index.js"></script>


  <script>
    var ctx = document.getElementById('myChart');
    var myChart = new Chart(ctx, {
      type: 'bar',
      data: {
        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
        datasets: [{
          label: '# of Votes',
          data: [12, 19, 3, 5, 2, 3],
          backgroundColor: [
            'rgba(255, 99, 132, 0.2)',
            'rgba(54, 162, 235, 0.2)',
            'rgba(255, 206, 86, 0.2)',
            'rgba(75, 192, 192, 0.2)',
            'rgba(153, 102, 255, 0.2)',
            'rgba(255, 159, 64, 0.2)'
          ],
          borderColor: [
            'rgba(255, 99, 132, 1)',
            'rgba(54, 162, 235, 1)',
            'rgba(255, 206, 86, 1)',
            'rgba(75, 192, 192, 1)',
            'rgba(153, 102, 255, 1)',
            'rgba(255, 159, 64, 1)'
          ],
          borderWidth: 1
        }]
      },
      options: {
        scales: {
          yAxes: [{
            ticks: {
              beginAtZero: true
            }
          }]
        }
      }
    });
  </script>

</body>

</html>

Nouvelle fonctionnalité

Nous allons rajouter une page dédiée à la librairie Chart.js dans notre projet.
C'est dans cette page que nous ferons tous nos tests et modifications.

Tout d'abord créons la nouvelle page avec les commandes Angular CLI correspondantes.

# Création de la page dédiée à Chart.js
ng generate component modules/application/chartjs  --module=app
ng generate module modules/application/chartjs --routing  --module=app
src/app/app-routing.module.ts
  {
    path: 'chartjs',
    loadChildren: () => import('./modules/application/chartjs/chartjs.module')
      .then(mod => mod.ChartjsModule)
  },
src/app/modules/application/chartjs/chartjs-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

import { ChartjsComponent } from './chartjs.component';

const routes: Routes = [
  { path: '', component: ChartjsComponent },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ChartjsRoutingModule { }
src/app/modules/application/chartjs/chartjs.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ChartjsComponent } from './chartjs.component';
import { ChartjsRoutingModule } from './chartjs-routing.module';

@NgModule({
  imports: [
    CommonModule,
    ChartjsRoutingModule
  ],
  exports: [
    ChartjsComponent
  ],
  declarations: [
    ChartjsComponent
  ],
  providers: [
  ],
})
export class ChartjsModule { }
src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { HomeComponent } from './modules/general/home/home.component';
import { NotFoundComponent } from './modules/general/not-found/not-found.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    NotFoundComponent,
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
src/modules/general/home/home.component.ts
        {
          name: 'Chart.js',
          description: 'Simple yet flexible JavaScript charting for designers & developers',
          icon: 'fa-share-alt-square',
          link: 'chartjs'
        },

Intégration de Chart.js dans Angular

Cela fonctionne dans notre prototype il nous reste qu'à l'intégrer dans notre application angular.

On commence par installer les dépendances nécessaires.

# Ajout des dépendances avec npm
npm install chart.js --save
npm install ng2-charts --save

Les modifications seront effectuées dans 4 fichiers

  • chartjs.component.html
  • chartjs.component.ts
  • chartjs.component.spec.ts
  • chartjs.module.ts
src/app/modules/application/chartjs/charts.component.html
<div class="col-12 col-sm-12 col-md-7 col-lg-7 col-xl-7">
  <div class="row">
    <div class="container-fluid">
      <div class="card p-4">
        <h5 class="card-title">Chart avec Chart.js</h5>
        <canvas baseChart [datasets]="datasets" [labels]="labels" [options]="options" [chartType]="type">
        </canvas>
      </div>
    </div>
  </div>
</div>
src/app/modules/application/chartjs/charts.component.ts
import { Component, OnInit } from '@angular/core';
import { ChartOptions, ChartType, ChartDataSets } from 'chart.js';
import { Color, BaseChartDirective, Label } from 'ng2-charts';


@Component({
  selector: 'app-chartjs',
  templateUrl: './chartjs.component.html',
  styleUrls: ['./chartjs.component.css']
})
export class ChartjsComponent implements OnInit {

  public type: ChartType = 'bar';

  public labels: Label[] = ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'];

  public datasets: ChartDataSets[] = [
    {
      label: '# of Votes',
      data: [12, 19, 3, 5, 2, 3],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      borderWidth: 1
    }];

  public options: ChartOptions = {
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true
        }
      }]
    }
  };


  constructor() { }

  ngOnInit() {
  }

}
src/app/modules/application/chartjs/charts.component.spec.ts
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { ChartjsComponent } from './chartjs.component';
import { ChartsModule } from 'ng2-charts';

describe('ChartjsComponent', () => {
  let component: ChartjsComponent;
  let fixture: ComponentFixture<ChartjsComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        ChartsModule,
      ],
      declarations: [ChartjsComponent]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(ChartjsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
src/app/modules/application/chartjs/charts.module.ts
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

import { ChartjsComponent } from './chartjs.component';
import { ChartjsRoutingModule } from './chartjs-routing.module';

import { ChartsModule } from 'ng2-charts';

@NgModule({
  imports: [
    CommonModule,
    ChartjsRoutingModule,
    ChartsModule,
  ],
  exports: [
    ChartjsComponent
  ],
  declarations: [
    ChartjsComponent
  ],
  providers: [
  ],
})
export class ChartjsModule { }

Tests

Il ne reste plus qu'à tester les différents scripts Angular.

# Développement
npm run start
http://localhost:4200/

# Tests
npm run lint
npm run test
npm run e2e

# Compilation
npm run build