• 20 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 28/11/2019

Enrichissez votre application

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Intégrez des services

Puisque Ionic est construit sur Angular, vous pouvez y intégrer des services comme dans une application web Angular.  Vous allez créer un service  AppareilsService  qui contiendra les données de vos appareils et qui suivra l'état des lumières : allumées ou éteintes.

Dans le dossier  src , créez un sous-dossier  services  et créez-y un fichier  appareils.service.ts .  Coupez l'array appareils de la page  AppareilsPage  et mettez-le dans votre nouveau service :

export class AppareilsService {
  appareilsList = [
    {
      name: 'Machine à laver',
      description: [
        'Volume: 6 litres',
        'Temps de lavage: 2 heures',
        'Consommation: 173 kWh/an'
      ]
    },
    {
      name: 'Télévision',
      description: [
        'Dimensions: 40 pouces',
        'Consommation: 22 kWh/an'
      ]
    },
    {
      name: 'Ordinateur',
      description: [
        'Marque: fait maison',
        'Consommation: 500 kWh/an'
      ]
    }
  ];
}

Puisque TypeScript vous permet de créer vos propres types et que vous allez ajouter de nouvelles propriétés aux appareils, il serait intéressant de créer un model  Appareil .  Créez un sous-dossier  models  dans le dossier  src  et créez-y un fichier  Appareil.ts  :

export class Appareil {
  name: string;
  description: string[];
  isOn: boolean;

  constructor(name: string) {
    this.name = name;
    this.isOn = false;
  }
}

Il y a même un raccourci TypeScript pour simplifier encore plus cette classe :

export class Appareil {
  description: string[];
  isOn: boolean;

  constructor(public name: string) {
    this.isOn = false;
  }
}

Maintenant, vous pouvez importer ce modèle dans votre service et, à condition d'ajouter la propriété  isOn  à chaque appareil, vous pouvez faire cela :

import { Appareil } from '../models/Appareil';

export class AppareilsService {
  appareilsList: Appareil[] = [
    {
      name: 'Machine à laver',
      description: [
        'Volume: 6 litres',
        'Temps de lavage: 2 heures',
        'Consommation: 173 kWh/an'
      ],
      isOn: true
    },
    {
      name: 'Télévision',
      description: [
        'Dimensions: 40 pouces',
        'Consommation: 22 kWh/an'
      ],
      isOn: true
    },
    {
      name: 'Ordinateur',
      description: [
        'Marque: fait maison',
        'Consommation: 500 kWh/an'
      ],
      isOn: false
    }
  ];
}

Il s'agit d'un service qui sera utilisé globalement, donc ajoutez-le à l'array  providers  de votre  AppModule .

Il faudra modifier les pages  AppareilsPage  et  SingleAppareilPage  pour profiter du nouveau service.  Le but étant de pouvoir modifier et conserver les données, au lieu de passer un objet  Appareil  entre les pages, vous passerez l'index de l'objet dans l'array.

Commencez par modifier  AppareilsPage  :

import { Component } from '@angular/core';
import { ModalController } from 'ionic-angular';
import { SingleAppareilPage } from './single-appareil/single-appareil';
import { Appareil } from '../../models/Appareil';
import { AppareilsService } from '../../services/appareils.service';

@Component({
  selector: 'page-appareils',
  templateUrl: 'appareils.html'
})
export class AppareilsPage {

  appareilsList: Appareil[];

  constructor(private modalCtrl: ModalController,
              private appareilsService: AppareilsService) {}

  ionViewWillEnter() {
    this.appareilsList = this.appareilsService.appareilsList.slice();
  }

  onLoadAppareil(index: number) {
    let modal = this.modalCtrl.create(SingleAppareilPage, {index: index});
    modal.present();
  }
}
<ion-header>
  <ion-navbar>
    <ion-title>Appareils</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
    <button ion-item
            icon-start
            *ngFor="let appareil of appareilsList; let i = index"
            (click)="onLoadAppareil(i)">
      <ion-icon name="power" [color]="appareil.isOn ? 'secondary' : 'danger'"></ion-icon>
      {{ appareil.name }}
    </button>
  </ion-list>
</ion-content>

Dans ce code :

  • Vous injectez le service.

  • Vous utilisez le hook  ionViewWillEnter  pour copier le contenu de l'array du service. Vous n'utilisez pas  OnInit , car, avec le fonctionnement par stack de la navigation, la page n'est pas forcément détruite au moment de naviguer. Donc  ngOnInit()  n'est pas obligatoirement exécutée à chaque visualisation de la page. Ionic vous propose  ionViewWillEnter() qui sera exécutée, comme son nom l'indique, juste avant que la page devienne la page active. 


  • Vous modifiez  onLoadAppareil()  pour passer l'index de l'appareil au lieu de l'objet lui-même.

  • Vous ajoutez une icône de type "power" qui sera verte si l'appareil est allumé, ou rouge s'il ne l'est pas (ceci vous permet de vous assurer que les actions d'allumage et d'extinction ont bien été prises en compte).

Maintenant, vous allez modifier  SingleAppareilPage  :

import { Component, OnInit } from '@angular/core';
import { NavParams, ViewController } from 'ionic-angular';
import { Appareil } from '../../../models/Appareil';
import { AppareilsService } from '../../../services/appareils.service';

@Component({
  selector: 'page-single-appareil',
  templateUrl: 'single-appareil.html',
})
export class SingleAppareilPage implements OnInit {

  index: number;
  appareil: Appareil;

  constructor(public navParams: NavParams,
              public viewCtrl: ViewController,
              public appareilsService: AppareilsService) {
  }

  ngOnInit() {
    this.index = this.navParams.get('index');
    this.appareil = this.appareilsService.appareilsList[this.index];
  }

  dismissModal() {
    this.viewCtrl.dismiss();
  }

  onToggleAppareil() {
    this.appareil.isOn = !this.appareil.isOn;
  }

}
<ion-header>
  <ion-navbar>
    <ion-buttons>
      <button ion-button clear (click)="dismissModal()">Fermer</button>
    </ion-buttons>
    <ion-title>{{ appareil.name }}</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-card>
    <ion-card-header>{{ appareil.name }}</ion-card-header>
    <ion-card-content>
      <p *ngFor="let line of appareil.description">{{ line }}</p>
    </ion-card-content>
    <ion-grid>
      <ion-row>
        <ion-col>
          <button
            ion-button
            full
            color="danger"
            [disabled]="!appareil.isOn"
            (click)="onToggleAppareil()">Eteindre</button>
        </ion-col>
        <ion-col>
          <button
            ion-button
            full
            color="secondary"
            [disabled]="appareil.isOn"
            (click)="onToggleAppareil()">Allumer</button>
        </ion-col>
      </ion-row>
    </ion-grid>
  </ion-card>
</ion-content>

Dans le TypeScript, vous récupérez la référence à l'appareil correspondant à l'index fourni : ainsi, vous pouvez créer  toggleAppareil()  pour modifier la propriété  isOn  directement.  Dans le template, vous associez cette méthode aux boutons, et vous désactivez dynamiquement les boutons selon l'état de la propriété  isOn .

Vous pouvez confirmer que le service fonctionne en vérifiant l'état allumé ou éteint des appareils dans  AppareilsPage  lorsque vous changez leur état dans  SingleAppareilPage  !

Ajoutez un menu latéral

Un élément d'UI que l'on retrouve dans beaucoup d'applications mobiles est le menu latéral.  Cela sert à créer un autre type de navigation pour vos utilisateurs, par exemple pour accéder à d'autres parties de l'application pour lesquelles vous ne souhaitez pas créer de tab.  Dans l'application exemple, vous allez l'utiliser pour accéder à une page Options, que vous utiliserez par la suite pour modifier le thème de l'application.

Créez d'abord rapidement une page  OptionsPage , non fonctionnelle pour l'instant, mais qui permettra d'illustrer l'utilisation du menu :

import { Component } from '@angular/core';

@Component({
  selector: 'page-options',
  templateUrl: './options.html'
})
export class OptionsPage {

}
<ion-header>
  <ion-navbar>
    <ion-title>Options</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <p>Modifiez les options de l'application ici !</p>
</ion-content>

Le menu sera créé à la racine de l'application, car il doit pouvoir modifier la  rootPage  du stack de navigation.  Vous allez donc utiliser le component  ion-menu  et l'ajouter au template  app.html  :

<ion-menu [content]="content">
  <ion-header>
    <ion-toolbar>
      <ion-title>Menu</ion-title>
    </ion-toolbar>
  </ion-header>
  <ion-content>
    <ion-list>
      <button ion-button icon-start (click)="onNavigate(tabsPage)">
        <ion-icon name="power"></ion-icon>
        Appareils
      </button>
      <button ion-button icon-start (click)="onNavigate(optionsPage)">
        <ion-icon name="options"></ion-icon>
        Options
      </button>
    </ion-list>
  </ion-content>
</ion-menu>
<ion-nav [root]="tabsPage" #content></ion-nav>

Ici :

  • vous attribuez une référence locale au component  ion-nav  et vous la référencez dans le component  ion-menu  , la liant à sa propriété  content  ;

  • vous utilisez un  ion-toolbar  plutôt qu'un  ion-navbar  , car le menu n'a pas besoin des éléments de navigation liés à  ion-navbar  ;

  • vous créez une  ion-list  avec des boutons correspondant aux pages sur lesquelles vous souhaitez naviguer (dont les variables et la méthode n'existent pas encore) ;

  • vous modifiez le nom de la variable pour la  rootPage , car vous allez tout de suite modifier   app.component.ts .

import { Component, ViewChild } from '@angular/core';
import { MenuController, NavController, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { TabsPage } from '../pages/tabs/tabs';
import { OptionsPage } from '../pages/options/options';
@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  tabsPage:any = TabsPage;
  optionsPage:any = OptionsPage;
  @ViewChild('content') content: NavController;

  constructor(platform: Platform,
              statusBar: StatusBar,
              splashScreen: SplashScreen,
              private menuCtrl: MenuController) {
    platform.ready().then(() => {
      statusBar.styleDefault();
      splashScreen.hide();
    });
  }

  onNavigate(page: any) {
    this.content.setRoot(page);
    this.menuCtrl.close();
  }
}

Dans ce code :

  • vous créez des variables contenant les pages sur lesquelles vos utilisateurs navigueront ;

  • vous utilisez la syntaxe  ViewChild()  d'Angular pour avoir accès au component  ion-nav  sur lequel vous avez mis la référence  content  ;

  • vous injectez le  MenuController  dans le constructor (n'oubliez pas l'import depuis  ionic-angular ) ;

  • vous implémentez la méthode  onNavigate()  qui utilise la méthode  setRoot()  du  NavController  (également à importer depuis  ionic-angular ) pour modifier la  rootPage  , et qui ferme ensuite le menu (car ce comportement n'est pas automatique).

Maintenant que le menu est créé, il faut pouvoir y accéder !  En termes d'UX, vous souhaitez que le menu soit accessible depuis la page Appareils, la page Réglages et la page Options.  Il faudra donc ajouter au  ion-navbar  de ces pages le component suivant :

<ion-buttons start>
      <button ion-button icon-only (click)="onToggleMenu()">
        <ion-icon name="menu"></ion-icon>
      </button>
</ion-buttons>

Et dans les components correspondants à ces pages, vous injecterez  MenuController  et impémenterez la méthode  onToggleMenu()  :

  onToggleMenu() {
    this.menuCtrl.open();
  }

Et voilà !  Votre application comporte maintenant un menu latéral, permettant de modifier la  rootPage  et de naviguer dans l'application.

Modifiez les styles

Comme avec une application web Angular, il est possible de customiser les styles de votre application Ionic.  Avant de parler du thème global de l'application, vous allez modifier les styles correspondant à une seule page, notamment  SingleAppareilPage .  Vous allez créer une classe pour quand l'appareil est allumé et une autre pour quand il est éteint ; vous utiliserez la liaison  [ngClass]  pour alterner entre les deux.

Dans votre dossier  single-appareil , ouvrez  single-appareil.scss  :

page-single-appareil {
  .is-on {
    ion-card-content, ion-card-header, ion-grid {
      background-color: #eeffee;
    }
  }
  .is-off {
    ion-card-content, ion-card-header, ion-grid {
      background-color: #ffeeee;
    }
  }
}

Une différence importante entre une application Angular classique et une application Ionic : vous n'avez pas besoin d'ajouter un array  styleUrls  à votre component.  C'est pour cela qu'il faut intégrer les styles dans le décorateur   page-single-appareil , qui correspond au selector du component.

Il ne vous reste plus qu'à intégrer ces classes à l'aide de  [ngClass]  dans le template :

<ion-card [ngClass]="{'is-on': appareil.isOn, 'is-off': !appareil.isOn}">

Ainsi, quand vous modifiez l'état d'un appareil, la couleur de fond du  ion-card  se modifie.

Changez de thème

Au-delà des styles "classiques", avec une feuille de style pour chaque component, Ionic intègre un système de thème permettant de modifier énormément d'attributs du thème global de l'application, et même d'ajouter des variables.  Sur le site ionicframework.com/docs/theming, vous trouverez la liste complète des variables que vous pouvez modifier — pour l'instant, vous allez commencer par les couleurs de l'application.

Ouvrez le fichier  variables.scss  dans le dossier  theme  et descendez à la section  Named Color Variables  :

// Named Color Variables
// --------------------------------------------------
// Named colors makes it easy to reuse colors on various components.
// It's highly recommended to change the default colors
// to match your app's branding. Ionic uses a Sass map of
// colors so you can add, rename and remove colors as needed.
// The "primary" color is the only required color in the map.

$colors: (
  primary:    #488aff,
  secondary:  #32db64,
  danger:     #f53d3d,
  light:      #f4f4f4,
  dark:       #222
);

Ici, vous trouvez les variables correspondant aux couleurs de votre application.  Vous pouvez, par exemple, modifier les couleurs  primary  ,  secondary  et  danger , afin de les rendre un peu moins fluorescentes :

$colors: (
  primary:    #264885,
  secondary:  #1C7437,
  danger:     #7f2020,
  light:      #f4f4f4,
  dark:       #222
);

Vous pouvez également ajouter des couleurs personnalisées.  Cela vous permet d'utiliser la même couleur à plusieurs endroits de votre application :

$colors: (
  primary:          #264885,
  secondary:        #1C7437,
  danger:           #7f2020,
  light:            #f4f4f4,
  dark:             #222,
  secondary-light:  #eeffee,
  danger-light:     #ffeeee
);

Ce sont les couleurs que vous avez ajoutées au  SingleAppareilPage . Vous pouvez donc modifier  single-appareil.scss  pour intégrer ces nouvelles couleurs à l'aide de la fonction  color  :

page-single-appareil {
  .is-on {
    ion-card-content, ion-card-header, ion-grid {
      background-color: color($colors, secondary-light);
    }
  }
  .is-off {
    ion-card-content, ion-card-header, ion-grid {
      background-color: color($colors, danger-light);
    }
  }
}

Ainsi, vous avez centralisé les couleurs de votre application, vous permettant de modifier plus facilement le thème.

N'oubliez pas que vous pouvez modifier énormément d'attributs du thème de votre application — la disposition des éléments, les polices, les padding/margin, etc. — en ajoutant les variables correspondantes à  variables.scss . Par exemple, pour réduire le padding de l'application (16px par défaut), il vous suffit d'ajouter :

$content-padding: 10px;

Et voilà ! Votre application basique fonctionne et a été enrichie avec l'intégration des services, l'ajout du menu latéral et la personnalisation du thème.

Exemple de certificat de réussite
Exemple de certificat de réussite