Blog ENI : Toute la veille numérique !
-25€ dès 75€ sur les livres en ligne, vidéos... avec le code FUSEE25. J'en profite !
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. Angular et Node.js
  3. Angular : les templates, bindings et directives
Extrait - Angular et Node.js Optimisez le développement de vos applications web avec une architecture MEAN (2e édition)
Extraits du livre
Angular et Node.js Optimisez le développement de vos applications web avec une architecture MEAN (2e édition) Revenir à la page d'achat du livre

Angular : les templates, bindings et directives

Les templates

Chaque composant qui produit un résultat affichable dans une page web le fait au travers de son template. Ce template correspond à sa vue dans la page unique de l’application monopage.

Ce template peut être soit codé dans le composant (nous le qualifierons alors de template inséré, en anglais « embedded »), soit externalisé dans un fichier séparé. Bien entendu, il est vraiment préférable de créer des templates externalisés, qui permettent une meilleure organisation, et donc une meilleure lisibilité du code.

Le template d’un composant est intégré dans la page web unique de l’application de deux manières différentes :

  • Soit de manière statique, à l’endroit où les balises ouvrante et fermante définies par son sélecteur apparaissent dans un autre template ou dans la page racine src/index.html : son sélecteur est déclaré en valeur de la propriété selector de l’objet paramétrant (décorant) le composant.

  • Soit de manière dynamique, quand le composant est invoqué par le contrôleur et que sa vue est associée à une balise nommée <router-outlet> (voir le chapitre Angular et la gestion des routes internes).

Intéressons-nous dans un premier temps à l’intégration des templates de manière statique. Soit un composant nommé MycomponentComponent créé avec Angular CLI.

Voici l’ossature de ce composant :

import { Component } from '@angular/core'; 
 
@Component({ 
 selector: "app-mycomponent", 
 templateUrl: "mycomponent.component.html", 
 styleUrls: [ "mycomponent.component.css" ]  
}) 
export class MycomponentComponent { 
  ... 
} 

Son template (c’est-à-dire sa vue), qui sera défini dans le fichier mycomponent.component.html, sera intégré à l’endroit où apparaîtront les balises <app-mycomponent></app-mycomponent> (elles forment une component directive) dans un autre template ou dans la page src/index.html.

Ce fonctionnement implique donc que des balises propres à Angular vont être intégrées...

Data bindings entre le composant et le template

Pour lier une variable (ou une méthode dans le cas de la gestion d’un écouteur d’événements) du composant au template, plusieurs types de liaisons (de data bindings) existent :

  • L’interpolation : une variable scalaire du composant est injectée dans le template. 

  • Le property binding : un attribut d’une balise, qui correspond à un attribut existant d’une balise HTML, ou à un nouvel attribut, est pris en charge par Angular.

  • L’event binding : une méthode du composant est appelée via un événement pris en charge par Angular.

  • Le two-way data binding : une variable du composant est liée de manière bidirectionnelle à une interface de saisie ou de sélection du template.

1. Accès aux éléments du DOM

Avant toute chose, voyons comment Angular permet de référencer simplement des éléments du DOM afin d’y accéder, et éventuellement de les modifier.

Le DOM représente la hiérarchie des objets créés par les balises HTML ainsi que leurs attributs et les informations textuelles qu’elles circonscrivent (et d’autres informations) en mémoire du navigateur. Les objets correspondant aux balises HTML sont alors nommés des éléments.

Angular offre la possibilité de faire apparaître dans une balise HTML une référence sur l’élément du DOM correspondant. Cette référence pourra ensuite être utilisée dans le code. Syntaxiquement, une référence est préfixée par un dièse.

Pour illustrer ceci, voici la création d’une référence nommée image associée à l’image affichée dans le template (avec Angular CLI, les ressources, dont les images, doivent être stockées dans le dossier src/assets) :

<img #imageRef src="assets/Angular.png" /> 

Par ailleurs, il est possible grâce aux directives attributs d’accéder aux attributs d’un élément du DOM (correspondant à une balise HTML) pour les modifier (voir la section Les directives attributs).

2. Interpolation d’une variable dans un template

L’interpolation d’une variable d’un...

Les directives

Une directive est une nouvelle balise ou un nouvel attribut pris en charge par Angular et inséré respectivement dans du code HTML ou dans une balise.

Les directives étendent donc le langage HTML.

Il y a globalement deux types de directives (le second type peut être raffiné en sous-types) :

  • Les directives « composants » (component directives), représentées par de nouvelles balises, qui insèrent les vues des composants dans le flux HTML : elles se confondent avec la mise en œuvre des composants.

  • Les directives données en attribut à une balise et qui conditionnent son affichage (et, plus généralement, son comportement).

Les directives données en attribut à une balise se déclinent sous différentes facettes :

  • Les directives structurelles (structural directives) qui permettent d’afficher zéro, une ou plusieurs fois les balises dans lesquelles elles apparaissent.

  • Les autres directives, nommées globalement directives attributs (attribute directives) qui permettent :

  • De modifier l’apparence de l’élément associé à la balise en modifiant ses attributs dans le DOM (sous condition ou non d’un événement, et par exemple dans le cadre du propertybinding).

  • De mettre en place un traitement particulier associé à la balise quand celle-ci est activée (par exemple, la directive [(ngModel)], qui permet de gérer le two-way data binding, ou la directive [routerLink], qui permet d’invoquer le contrôleur sur l’activation d’une ancre).

Avant d’examiner ces directives plus en détail, voici un petit aperçu des différentes syntaxes :

  • Des chevrons encadrent une directive composant : <Directive>.

  • Un astérisque vient en préfixe d’une directive structurelle : *Directive="...".

  • Des crochets encadrant une directive attribut avec une valeur à évaluer : [Directive]="..." (et s’il n’y a pas de valeur à évaluer, le nom de la directive est directement spécifié).

1. Les directives structurelles

Les directives structurelles permettent de contrôler la production des balises HTML dans un template.

Syntaxiquement, elles sont introduites par un astérisque :

  • *ngFor : contrôle...

Les pipes

Au sein d’un template, les pipes (les filtres) permettent de transformer une donnée : la donnée initiale est fournie en entrée du pipe, qui produit en sortie la donnée transformée suivant la syntaxe :

<donnéeEnEntrée> | <donnéeEnSortie> 

Seulement quelques pipes sont proposés par Angular, notamment UpperCasePipe et LowerCasePipe.

Par exemple dans un template, vous pouvez transformer en majuscules tous les caractères de la chaîne contenue dans la variable interpolée nom :

{{ nom | UpperCase}} 

Mais les pipes proposés par Angular (à l’heure de la rédaction de cet ouvrage) étant en nombre très réduit, vous pouvez aussi créer vos propres pipes (par exemple, un pipe très utile qui trie les éléments d’une collection sur une de ses propriétés).

 Pour ce faire, utilisez la commande d’Angular CLI qui produit l’ossature d’un pipe :

ng generate pipe <nomDuPipe> 

ou sa version abrégée :

ng g p <nomDuPipe> 

Voici le résultat de cette commande, avec comme nom de pipe, sort :

import { Pipe, PipeTransform } from '@angular/core'; 
 
@Pipe({ 
name: 'sort' 
}) 
export class SortPipe implements PipeTransform { 
 
 transform(value: any, args?: any): any { 
    return null; 
 } 
 
} 

Dans cette ossature, la transformation opérée par le pipe est gérée par la méthode transform(), qui reçoit en paramètres :

  • L’entrée donnée au pipe (par défaut n’importe...

Exemple de synthèse : un formulaire d’authentification

Pour illustrer de manière synthétique la plupart des bindings que nous avons décrits, voici l’exemple du composant AuthComponent. Nous en donnons juste une ossature possible.

Voici les fichiers qui composent cet exemple :

  • AUTH/src/app/app.component.ts (non présenté) : le composant principal.

  • AUTH/src/app/app.component.html : le template du composant principal.

  • AUTH/src/app/auth/auth.component.ts : le composant d’authentification.

  • AUTH/src/app/auth/auth.component.html : le template du composant d’authentification.

  • AUTH/src/app/app.module.ts (non présenté) : le module recensant les codes de l’application.

Le template du composant principal (fichier app.component.html) est simplissime :

<app-auth></app-auth> 

Voici l’ossature du composant (fichier auth/auth.component.ts) qui gère un formulaire d’authentification.

Ce composant met en œuvre :

  • Les chaînes de caractères d’identification login et password.

  • Le booléen isLoggedIn (géré par ailleurs) qui enregistre si l’internaute est déjà authentifié.

  • La méthode onSubmit() appelée quand le formulaire est soumis.

  • La méthode logout() qui enregistre la déconnexion de l’internaute.

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

Le fil rouge : création d’un composant qui affiche les produits

 Pour commencer à développer le côté client (le « client-side ») de l’application d’e-commerce, créez avec Angular CLI un projet nommé OnlineSalesStep1.

ng new OnlineSalesStep1 

Angular CLI crée un module initiant (« bootstrappant ») un premier composant qui est le composant principal de l’application (à cette étape).

Ce composant correspond à la première version de ProductDisplayComponent (voir la section Imbrication des templates).

Différents fichiers sont générés, et plus particulièrement (par ordre de création) :

  • src/app/app.component.css : ce fichier contient la feuille de style associée au template du composant principal.

  • src/app/app.component.html : ce fichier contient le template du composant principal (sa vue).

  • src/app/app.component.ts : ce fichier contient la classe TypeScript qui implémente les traitements métier du composant principal.

  • src/app/app.module.ts : ce fichier spécifie la liste des composants gérés par le module courant.

  • src/index.html : la page web de l’application dans laquelle sont inclus de manière arborescente les différents templates des composants.

  • src/main.ts : le code qui initie (bootstrappe) le module racine de l’application.

Vous allez maintenant élaborer le composant qui affiche les informations sur les produits à vendre contenus dans une collection créée dans un premier temps « en dur » dans le code (vous verrez dans le chapitre Angular et la connexion à Node.js : les services comment Angular peut accéder à une base de données MongoDB dans laquelle cette collection sera par la suite gérée).

1. Le composant

Créez l’ossature du composant ProductDisplayComponent avec la commande ng d’Angular CLI :

ng g c productDisplay 

Quatre fichiers sont créés dans le dossier src/app/product-display :

  • product-display.component.ts : ce fichier contient la classe TypeScript qui implémente le composant.

  • product-display.component.html : ce fichier contient le template du composant.

  • product-display.component.css : ce fichier contient la feuille de style associée au template.

  • product-display.component.spec.ts...

Bilan des acquis de ce chapitre

Dans ce chapitre, nous avons étudié la construction des vues des composants, c’est-à-dire les templates. Nous avons d’abord vu comment ces templates sont intégrés les uns dans les autres à partir de la page HTML de plus haut niveau src/index.html pour constituer la page unique de l’application monopage.

Puis nous avons décrit la mécanique qui permet de lier un attribut ou une méthode de la classe TypeScript implémentant un composant, à son template. Ce lien (ce « binding ») lie donc la vue (le template) au modèle (l’implémentation dans une classe TypeScript des traitements métier du composant).

Nous avons décliné ce data binding selon différentes facettes :

  • L’interpolation d’une variable dans le template.

  • La gestion d’un attribut d’une balise (que ce soit en surcharge d’un attribut existant de la balise ou pour gérer un nouvel attribut) par Angular (le property binding).

  • L’appel d’une méthode du composant (plus exactement, de la classe qui l’implémente) à partir d’un événement capturé par le template (l’event binding).

  • Le couplage bidirectionnel d’une variable entre la vue et le modèle d’un composant de telle sorte que la mise à jour de cette variable...