• 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

Ajoutez des formulaires

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

Jusqu'ici, votre application reste statique. Malgré son enrichissement, toutes les données sont codées en dur et l'utilisateur ne peut pas interagir avec de manière pérenne.  Vous allez maintenant changer cela en ajoutant des formulaires à l'application et en la liant à un backend Firebase.  Vous découvrirez également quelques-uns des native features des smartphones mis à disposition par Ionic.

Vous allez utiliser les deux méthodes Angular pour la création de formulaires dans votre application.  D'abord, vous créerez un formulaire par la méthode template pour que vos utilisateurs puissent définir une heure d'allumage et une heure d'extinction pour chaque appareil.  Ensuite, vous créerez un autre formulaire, par la méthode réactive, permettant de modifier le nom de l'appareil et d'ajouter ou de supprimer des lignes de description.  Pour ces deux formulaires, vous découvrirez des components Ionic qui pourront les enrichir, proposant une expérience utilisateur plus approfondie.

La méthode template

Vous allez maintenant utiliser la méthode template pour créer un formulaire qui permet d'ajouter une heure d'allumage et une heure d'extinction pour les appareils.  Pour préparer le terrain, commencez par modifier le model :

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

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

Ensuite, vous allez modifier l'array du service pour prendre en compte ce changement ; chaque appareil devra prendre cette forme :

{
      name: 'Machine à laver',
      description: [
        'Volume: 6 litres',
        'Temps de lavage: 2 heures',
        'Consommation: 173 kWh/an'
      ],
      isOn: true,
      startTime: '',
      endTime: ''
}

Vous pouvez maintenant commencer à créer le template du formulaire dans  SingleAppareilPage , sous le  ion-grid  et à l'intérieur du  ion-card  :

<form #f="ngForm" (ngSubmit)="onSubmitForm(f)">
      <ion-list>
        <ion-item>
          <ion-label>Heure d'allumage</ion-label>
          <ion-datetime displayFormat="HH:mm" name="startTime" [(ngModel)]="appareil.startTime"></ion-datetime>
        </ion-item>
        <ion-item>
          <ion-label>Heure d'extinction</ion-label>
          <ion-datetime displayFormat="HH:mm" name="endTime" [(ngModel)]="appareil.endTime"></ion-datetime>
        </ion-item>
      </ion-list>
</form>

Le formulaire fonctionne comme tout formulaire template Angular : vous ajoutez une référence locale de type  ngForm , vous liez la méthode de soumission du formulaire à  ngSubmit  et vous ajoutez la directive  ngModel  à chaque control.  Dans ce cas précis, vous ajoutez la liaison à double sens afin que les controls lisent les propriétés de l'appareil si elles existent déjà.

Les  ion-datetime  sont des components Ionic permettant à l'utilisateur de choisir une date et/ou une heure selon le format que vous précisez.  Ici, il faut que l'utilisateur puisse choisir des horaires, donc le format est  HH:mm.  Les données retournées seront des string qui suivent le même format :  '09:45'  ,  '15:00' , etc.

Il faut ajouter un bouton pour soumettre le formulaire. Vous allez également intégrer la suppression des horaires, donc il faudra aussi un bouton pour cette fonctionnalité, le tout en dessous du  ion-list , mais toujours à l'intérieur du  form  :

<form #f="ngForm" (ngSubmit)="onSubmitForm(f)">
      <ion-list>
        <ion-item>
          <ion-label>Heure d'allumage</ion-label>
          <ion-datetime displayFormat="HH:mm" name="startTime" [(ngModel)]="appareil.startTime"></ion-datetime>
        </ion-item>
        <ion-item>
          <ion-label>Heure d'extinction</ion-label>
          <ion-datetime displayFormat="HH:mm" name="endTime" [(ngModel)]="appareil.endTime"></ion-datetime>
        </ion-item>
      </ion-list>
      <button type="button"
              ion-button
              full
              color="danger"
              (click)="onDeleteHours()">
        Supprimer horaires
      </button>
      <button type="submit"
              ion-button
              full
              color="secondary">
        Enregistrer horaires
      </button>
</form>

Le bouton Enregistrer n'a pas besoin de liaison  (click) , puisque son type  submit  signale à Angular d'exécuter la méthode liée au  ngSubmit  du formulaire.  Le bouton Supprimer doit être de type  button  pour ne pas risquer de soumettre le formulaire, et exécutera la méthodeonDeleteHours() que vous allez créer maintenant, ainsi que la méthode  onSubmitForm() :

onSubmitForm(form: NgForm) {
    console.log(form.value);
    this.dismissModal();
}

onDeleteHours() {
    this.appareil.startTime = '';
    this.appareil.endTime = '';
    this.dismissModal();
}

Pour l'instant, la méthode  onSubmitForm()  ne fera qu'une  console.log() , simplement pour montrer que les données sont disponibles et fonctionnent. Dans ce component, vous manipulez déjà l'appareil du service, donc les champs du formulaire qui emploient la liaison à double sens modifient directement l'appareil et vous n'avez pas besoin de manipuler les données qui s'y trouvent.  La méthode ferme ensuite la modal pour que l'utilisateur comprenne que ses changements ont bien été enregistrés.  La méthode  onDeleteHours()  remet à zéro les horaires et ferme la modal.

Grâce à ce formulaire géré par la méthode template, vos utilisateurs peuvent ajouter des heures d'allumage et d'extinction pour leurs appareils électriques.  Prochaine étape : créer un formulaire permettant aux utilisateurs de créer leur propre appareil.

La méthode réactive

Pour ce formulaire, vous allez créer une nouvelle page  AppareilFormPage qui permettra la création d'un nouvel appareil, dans un sous-dossier  appareil-form  du dossier  appareils .  Commencez par le fichier TS en préparant le formulaire :

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

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

  appareilForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {}

  ngOnInit() {
    this.initForm();
  }

  initForm() {
    this.appareilForm = this.formBuilder.group({
      name: ['', Validators.required],
      description: this.formBuilder.array([])
    });
  }
}

Pour intégrer la fonctionnalité du  FormArray , il faut une méthode qui le retourne sous forme de  FormArray  (sans oublier d'importer  FormArray  depuis  @angular/forms ) :

getDescriptionArray() {
    return this.appareilForm.get('description') as FormArray;
}

Vous pouvez maintenant commencer à préparer le template :

<ion-header>
  <ion-navbar>
    <ion-title>Nouvel appareil</ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <form [formGroup]="appareilForm">
    <ion-list>
      <ion-item-divider>Informations</ion-item-divider>
      <ion-item>
        <ion-label>Nom</ion-label>
        <ion-input placeholder="Appareil" formControlName="name"></ion-input>
      </ion-item>
      <ion-item-divider>Description</ion-item-divider>
      <div formArrayName="description">
        <ion-item *ngFor="let control of getDescriptionArray().controls; let i = index"></ion-item>
      </div>
    </ion-list>
  </form>
</ion-content>

Les  ion-item-divider  permettent de diviser un  ion-list  en différentes parties. Intégrer un  ion-label  et un  ion-input  dans un  ion-item  permet une mise en page automatique et propre.

Afin de visualiser votre progrès, ajoutez  AppareilFormPage  dans les  declarations  et  entryComponents  de votre  AppModule , et créez un bouton sur  AppareilsPage  pour y accéder :

<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>
  <button ion-button full (click)="onNewAppareil()">Nouvel appareil</button>
</ion-content>
onNewAppareil() {
    this.navCtrl.push(AppareilFormPage);
}

N'oubliez pas d'injecter  NavController  dans le constructor, l'ayant auparavant importé depuis  ionic-angular !

Maintenant, vous allez permettre à l'utilisateur d'ajouter des champs description. Créez d'abord la méthode :

onAddDescription() {
    let newControl = this.formBuilder.control('');
    this.getDescriptionArray().controls.push(newControl);
}

Puis intégrez-la dans le template, en y ajoutant le  ion-input  correspondant :

<div formArrayName="description">
    <ion-item *ngFor="let control of getDescriptionArray().controls; let i = index">
        <ion-input [formControlName]="i" placeholder="{{i+1}}."></ion-input>
    </ion-item>
</div>
</ion-list>
<button ion-button full (click)="onAddDescription">Ajouter une ligne</button>

Vous allez également permettre à l'utilisateur de supprimer une ligne de description.  D'abord la méthode :

onRemoveDescription(index: number) {
    this.getDescriptionArray().removeAt(index);
}

Et ensuite le template, en profitant de l'index  i  :

<div formArrayName="description">
        <ion-item *ngFor="let control of getDescriptionArray().controls; let i = index">
          <ion-icon item-start
                    name="remove-circle"
                    color="danger"
                    (click)="onRemoveDescription(i)">
          </ion-icon>
          <ion-input [formControlName]="i" [placeholder]="i+1 + '.'"></ion-input>
        </ion-item>
</div>

Ajouter la directive  item-start  au  ion-icon  aligne correctement les icônes à gauche par rapport au contenu des  ion-item .

Maintenant, il faut pouvoir ajouter un appareil à l'array du service.  Commencez par modifier légèrement le model pour qu'il y ait toujours un array description pour un Appareil, même s'il est vide :

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

  constructor(public name: string) {
    this.description = [];
    this.isOn = false;
    this.startTime = '';
    this.endTime = '';
  }
}

Ensuite, ajoutez une méthode au service permettant l'ajout d'un nouvel appareil :

  addAppareil(appareil: Appareil) {
    this.appareilsList.push(appareil);
  }

Ensuite, de retour dans le component, ayant importé et injecté  AppareilsService  et  NavController , créez la méthode pour soumettre le formulaire  :

  onSubmitForm() {
    let newAppareil = new Appareil(this.appareilForm.get('name').value);
    for (let control of this.getDescriptionArray().controls) {
      newAppareil.description.push(control.value);
    }
    this.appareilsService.addAppareil(newAppareil);
    this.navCtrl.pop();
  }

Et dans le template :

    <button ion-button full (click)="onAddDescription()">Ajouter une ligne</button>
    <button ion-button full (click)="onSubmitForm()">Enregistrer</button>

Ça y est ! Vos utilisateurs peuvent maintenant ajouter de nouveaux appareils à l'application, grâce à ce formulaire géré par la méthode réactive.

Félicitations !  :D Votre application est fonctionnelle, dynamique et interactive.  Cependant, les données sont perdues à chaque redémarrage de l'application.  Dans le chapitre suivant, vous allez apprendre à créer et à intégrer un backend Firebase, afin de conserver et de sécuriser les données.

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