Cours 420-2D7-LL Développement web

*** lundi, 20 avril 2026 --> semaine 12 !!! ***



Semaine 8 - Directives et Pipes

 

Télécharger : 3 - Théorie Semaine 8 (Structurez le document avec des Directives).docx

  

 

3 - Structurez le document avec des Directives

                                                                                                                                                    

Partie 3 (Voitures7)

1.       Les directives. 

Les directives sont des instructions intégrées dans le DOM (Document Object Model : les éléments HTML affichés par le navigateur) que vous utiliserez presque systématiquement quand vous créerez des applications Angular.  Quand Angular lit votre template(HTML) et rencontre une directive qu'il reconnait, il suit les instructions correspondantes.  Vous pouvez créer vos propres directives, mais dans le cadre de ce cours, nous allons uniquement aborder certaines directives qui sont fournies avec Angular et qui sont extrêmement utiles.

Il existe deux types principaux de directive : les directives structurelles et les directives par attribut.

Zone de Texte:  Les directives structurelles

Ce sont des directives qui, comme leur nom l'indique, modifient la structure du document.   Dans ce chapitre, vous allez en découvrir deux (il en existe d'autres) :  *ngIf  , pour afficher des données de façon conditionnelle, et  *ngFor , pour itérer des données dans un tableau "array", par exemple.

*ngIf

Un component auquel on ajoute la directive  *ngIf="condition"  ne s'affichera que si la condition est "truthy" (elle retourne la valeur  true  où la variable mentionnée est définie et non-nulle), comme un statement  if  classique.

Pour une démonstration simple, ajoutez une <div> rouge qui ne s'affichera que si la voiture est Non disponible:  marques-voitures.component.html à

 

<li class="list-group-item">

    <div style="width:20px;height:20px;background-color:red;"

        *ngIf="voituresStatus === 'Non disponible'"></div>

    <h4>Voiture : {{ voituresName }} -- Statut : {{ getStatus() }}</h4>

    <input type="text" class="form-control" [(ngModel)]="voituresName">


</li>

 

 

 

Dans le fichier .ts du component, ne pas oublier d'ajouter le import suivant:

import { Component, Input, OnInit } from '@angular/core';

import { FormsModule} from '@angular/forms';

import { CommonModule } from '@angular/common';

 

@Component({

  selector: 'app-marques-voitures',

  imports: [FormsModule,CommonModule],

  templateUrl: './marques-voitures.component.html',

  styleUrl: './marques-voitures.component.scss'

})

export class MarquesVoituresComponent implements OnInit{

    

  constructor(){}

 

 

 

*** Attention * Attention * Attention ***

*ngIf sera bientôt déprécié "Depreciated"

Remplacer le vieux code dans le à marques-voitures.html par : (@if)

    <!-- <div style="width:20px;height:20px;background-color:red;"

    *ngIf="voituresStatus === 'Non disponible'"></div> -->

 

    @if (voituresStatus === 'Non disponible') {

       <div style="width:20px;height:20px;background-color:red;"></div>

    } @else if (voituresStatus === 'Disponible') {

       <div style="width:20px;height:20px;background-color:green;"></div>

    } @else {

        <!-- Rien du tout -->

    }

 

 

*ngFor

Lorsque l'on ajoute la directive  *ngFor="let obj of myArray"  à un component, Angular itérera le tableau "array"  myArray  et affichera un component par objet  obj .  Pour en comprendre l'utilisation, je vous propose de modifier la façon dont votre application génère les voitures de mon exemple.

On peut imaginer que votre application récupère, depuis un serveur, un array contenant tous les voitures et leurs états.  Pour l'instant, créez cet array directement dans  app.component.ts  :

export class AppComponent {

  title = 'Voitures7 de rêves de Mers 2026';

  isAuth = false;

 

  voitures = [

    {

      name: 'Bugatti',

      status: 'Non disponible'

    },

    {

      name: 'Ferrari',

      status: 'Disponible'

    },

    {

      name: 'Lambhorgini',

      status: 'Non disponible'

    }

  ];

 

  constructor() {

 

Vous avez un array avec trois objets, chaque objet ayant une propriété  name  et une propriété  status .  Vous pourriez même créer une interface ou une class TypeScript  Voiture , mais dans ce cas simple ce n'est pas nécessaire.

Maintenant la magie  *ngFor  : à app.component.html

<div class="container">

  <div class="row">

    <div class="col-xs-12">

      <h2>Les voitures</h2>

      <ul class="list-group">

        <app-marques-voitures *ngFor="let totovoiture of voitures"

                              [voituresName]="totovoiture.name"

                              [voituresStatus]="totovoiture.status"></app-marques-voitures>

      </ul>

      <button class="btn btn-success"

      [disabled]="!isAuth"

      (click)="onAllumer()">Tous disponible</button>

 

    </div>

  </div>

</div>

 

Le statement  "let totovoiture of voitures", comme dans une for loop classique, itère pour chaque élément  totovoiture  (nom arbitraire) de l'array  voitures  .  Après cette directive, vous pouvez maintenant utiliser l'objet  totovoiture , dont vous connaissez la forme, à l'intérieur de cette balise HTML.  Vous pouvez donc utiliser le property binding, et y passer les propriétés  name  et  status  de cet objet.

N'oubliez pas l'astérisque devant ces directives, qui signifie à Angular de les traiter comme directives structurelles !

Dans le fichier app.ts du component, ne pas oublier d'ajouter le import suivant:

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

import { MonPremier } from './mon-premier/mon-premier';

import { MarquesVoitures } from './marques-voitures/marques-voitures';

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

import { CommonModule } from '@angular/common';

 

@Component({

  selector: 'app-root',

Zone de Texte:    standalone: true,

  imports: [MonPremier,MarquesVoitures,CommonModule],

  templateUrl: './app.component.html',

  styleUrl: './app.component.scss'

})

 

*** Attention * Attention * Attention ***

*ngFor sera bientôt déprécié "Depreciated"

Remplacer le vieux code dans le à app.html par : (@for)

        <!--<app-marques-voitures *ngFor="let totovoiture of voitures"

                              [voituresName]="totovoiture.name"

                              [voituresStatus]="totovoiture.status"></app-marques-voitures> -->

           @for (item of voitures; track item.name) {

            <app-marques-voitures

              [voituresName] =  item.name

              [voituresStatus] = item.status >

            </app-marques-voitures> }

 

 

 

Les directives par attribut

À la différence des directives structurelles, les directives par attribut modifient le comportement d'un objet déjà existant.  Vous avez déjà utilisé une directive de ce type sans le savoir : la directive  ngModel  que vous avez employée pour le two-way binding, qui modifie la valeur du  <input>  et répond à tout changement qu'on lui apporte.  Je vais vous montrer deux autres exemples très utiles :  ngStyle  et  ngClass , qui permettent d'attribuer des styles ou des classes de manière dynamique.

ngStyle

Cette directive permet d'appliquer des styles à un objet du DOM (Document Object Model : les éléments HTML affichés par le navigateur) de manière dynamique. Imaginez que, pour l'application des voitures, vous souhaitiez modifier la couleur du texte selon si la voiture est disponible ou non, disons vert pour Disponible, rouge pour Non disponible.   ngStyle  vous permet de faire cela :

è marques-voitures.component.html

<li class="list-group-item">

    <!-- <div style="width:20px;height:20px;background-color:red;"

    *ngIf="voituresStatus === 'Non disponible'"></div> -->

 

    @if (voituresStatus === 'Non disponible') {

       <div style="width:20px;height:20px;background-color:red;"></div>

    } @else if (voituresStatus === 'Disponible') {

       <div style="width:20px;height:20px;background-color:green;"></div>

    } @else {

        <!-- Rien du tout -->

    }

 

    <h4 [ngStyle]="{color: getColor()}">Voiture : {{ voituresName }} -- Statut : {{ getStatus() }}</h4>

    <input type="text" class="form-control" [(ngModel)]="voituresName">

</li>

 

ngStyle  prend un objet JS de type clé-valeur, avec comme clé le style à modifier, et comme valeur la valeur souhaitée pour ce style. Ici, vous faites appel à une fonction getColor()  dans  marques-voitures.component.ts que vous allez maintenant créer :

  constructor() { }

 

  ngOnInit(): void {

  }

  getStatus() {

    return this.voituresStatus;

  }

 

  getColor() {

    if(this.voituresStatus === 'Non disponible'){

      return 'red';

    }

    else if(this.voituresStatus === 'Disponible'){

      return 'green';

    }

    else {return 'black'}

 

  }

 

}

 

Cette fonction retourne la valeur  'green'  si la voiture est Disponible, et  'red'  s'il est Non disponible, (noir pour autre cas !!!!!) modifiant ainsi la couleur du texte dans le template (HTML).

ngClass

Au-delà de modifier des styles directement, il peut être très utile d'ajouter des classes CSS à un élément de manière dynamique.  Comme  ngStyle ,  ngClass  prend un objet clé-valeur, mais cette fois avec la classe à appliquer en clé, et la condition en valeur.

Pour cet exemple, je vous propose d'appliquer des classes Bootstrap à la balise  <li>  en fonction du statut de la voiture : à marques-voitures.component.html

<li  [ngClass]="{   'list-group-item': true,

                    'list-group-item-success': voituresStatus === 'Disponible',

                    'list-group-item-danger': voituresStatus === 'Non disponible'}">

<li class="list-group-item">

    <!-- <div style="width:20px;height:20px;background-color:red;"

    *ngIf="voituresStatus === 'Non disponible'"></div> -->

 

    @if (voituresStatus === 'Non disponible') {

       <div style="width:20px;height:20px;background-color:red;"></div>

    } @else if (voituresStatus === 'Disponible') {

       <div style="width:20px;height:20px;background-color:green;"></div>

    } @else {

        <!-- Rien du tout -->

    }

 

    <h4 [ngStyle]="{color: getColor()}">Voiture : {{ voituresName }} -- Statut : {{ getStatus() }}</h4>

    <input type="text" class="form-control" [(ngModel)]="voituresName">

</li>

 

Angular appliquera donc systématiquement la classe  list-group-item , et selon le contenu de la variable  voituresStatus , appliquera l'une ou l'autre des deux autres classes.  Vous pouvez bien évidemment créer vos propres classes et les utiliser ; j'ai simplement choisi des classes Bootstrap pour simplifier l'explication.

Que ce soit pour  ngStyle  ou pour  ngClass , les objets JS peuvent être des variables valables dans votre TypeScript qui seront ensuite référencées par la directive, par exemple :  [ngClass]="myClassObject" .

 

xxx

Réf. : https://openclassrooms.com/fr/courses/4668271-developpez-des-applications-web-avec-angular/5088481-structurez-le-document-avec-des-directives

 

 


 

 

 

Télécharger : 4 - Théorie Semaine 8 (Modifiez les données en temps réel avec les Pipes).docx

 

4 - Modifiez les données en temps réel avec les Pipes

                                                                                                                                                     

Partie 4 (Voitures8)

1.       Les Pipes. 

Les pipes (/pʌɪp/) prennent des données en input, les transforment, et puis affichent les données modifiées dans le DOM (Document Object Model : les éléments HTML affichés par le navigateur).  Il y a des pipes fournis avec Angular, et vous pouvez également créer vos propres pipes si vous en avez besoin.  Je vous propose de commencer avec les pipes fournis avec Angular.

Utilisez et paramétrez les Pipes

Un pipe que l'on utilise très souvent est DatePipe , qui analyse des objets JS de type Date et qui les affiche d'une manière plus lisible que leur encodage de base.  Par exemple, imaginez que vous vouliez ajouter la date de la dernière mise à jour dans votre application des voitures.  Commencez par créer cet objet dans  AppComponent  et par l'afficher directement dans le template (HTML):

è app.component.ts

export class App {
  title = 'Voitures8 de Mers 2026';
  isAuth = false;
  lastUpdate = new Date();
 
è app.component.html
<h2>Les voitures</h2>
<p>Mis à jour : {{ lastUpdate }}</p>
<ul class="list-group">
  

L'objet Date a bien été créé, mais sous sa forme actuelle, il n'est pas très utile. L'avantage d'un pipe est de pouvoir modifier l'affichage de cet objet sans en modifier la nature.  Ajoutons le DatePipe dans le template grâce au caractère | :

<p>Mis à jour : {{ lastUpdate | date }}</p>

  

La date s'affiche maintenant sous la forme "Oct 06, 2017" dans le DOM ; c'est déjà beaucoup plus lisible, mais on peut faire mieux.  Angular permet de paramétrer DatePipe en lui passant un argument de formatage, par exemple :

 
<p>Mis à jour : {{ lastUpdate | date: 'short' }}</p>
<p>Mis à jour : {{ lastUpdate | date: 'yMMMMEEEEd' }}</p>
 
  

Il y a beaucoup de possibilités de formatage de DatePipe : vous trouverez plus d'informations dans la documentation d'Angular.

Utilisez une chaîne de Pipes

Vous pouvez avoir besoin de plusieurs pipes pour un seul élément du DOM.  Imaginez, par exemple, que vous souhaitiez afficher la date de l'exemple précédent en majuscules.  Vous aurez simplement à faire comme cela :

<p>Mis à jour : {{ lastUpdate | date: 'yMMMMEEEEd' | uppercase }}</p>

L'ordre des pipes est important. Si vous les inversez, UpperCasePipe ne fonctionnera pas et votre application n'affichera rien. Pensez à l'ordre dans lequel les modifications doivent être exécutées et mettez les pipes dans cet ordre.

async

Le pipe async est un cas particulier mais extrêmement utile dans les applications Web, car il permet de gérer des données asynchrones, par exemple des données que l'application doit récupérer sur un serveur.  Dans les chapitres suivants, vous apprendrez à communiquer avec un serveur extérieur, mais pour l'instant, vous allez simuler ce comportement en créant une Observable qui va se résoudre au bout de quelques secondes.  Modifier  lastUpdate  comme suit :

  lastUpdate = new Observable((observer) => {    setTimeout(() => observer.next(new Date().toString()), 4000);  });

Si vous enregistrez le fichier, l'application vous créera une erreur :

  

En effet, au moment de générer le DOM,  lastUpdate  est encore une Observable et n'a pas de valeur modifiable par les pipes.

Ce genre d'erreur n'est pas limitée à l'utilisation de pipe.  Si vous essayez d'afficher une Observable sans pipe, elle s'affichera "[object Observable]".

Il nous faut donc ajouter AsyncPipe en début de chaîne pour dire à Angular d'attendre l'arrivée des données avant d'exécuter les autres pipes :

<p>Mis à jour : {{ lastUpdate | async }}</p>

Assurer vous que la ligne suivant est présente dans votre fichier .TS

import { Observable } from 'rxjs';

 
 
Maintenant, quand votre page recharge, le champ "Mis à jour" est vide et puis, au bout de quatre secondes, les données retournées par l' Observable sont reçues, modifiées par les pipes suivants, et affichées.
  

Dernière essai et 1 à faire : 

 

Remplacer la ligne setTimeout(() => observer.next(new Date().toString()), 4000);

 

Par:     if (typeof window !== 'undefined') {

                         window.setInterval(()=>{observer.next(new Date().toString())},1000);

            }

 

Pour que ça fonctionne = Faire : localhost:4200/index.html

Bonus:

if (typeof window !== 'undefined') {

     window.setInterval(()=>{observer.next(new Date().toLocaleString("fr-CA"))},1000);

            }

 

Et observer le résultat !!!!!!!!!!

 

  

Félicitations !  À ce stade, vous savez :

·        Comment créer les composantes d'une application Angular : les components. Vous savez leur passer des données, réagir aux événements qu'ils déclenchent et même faire les deux en même temps !

·        Utiliser des directives pour structurer votre application et en modifier le contenu de manière dynamique ;

·        Profiter des pipes pour modifier l'affichage des données sans en changer la nature.

Avec ces éléments, vous avez déjà de quoi créer des applications basiques et fonctionnelles, mais Angular est extrêmement riche et permet d'intégrer facilement d'autres fonctionnalités : c'est précisément le sujet de la prochaine partie de ce cours.

 

Réf. : https://openclassrooms.com/fr/courses/4668271-developpez-des-applications-web-avec-angular/5088481-structurez-le-document-avec-des-directives

Réf.: https://angular.io/api/common/AsyncPipe

 

 

 

 


   

Voici mes coordonnees: Stéphane Mercier (Mers), stephane.mercier@cegeplevis.ca, 418 833-5110, poste 5511, Local G205A (disponnible par MIO)

Tout droit réservé à personne !!!

.