Interactions TypeScript - HTML

Angular propose de nombreuses méthodes pour échanger les données au sein de l’application. À l’intérieur d’un même composant, il y a 4 techniques principales :

Interactions TypeScript - HTML

L'interpolation

L’interpolation permet de prendre des valeurs du TypeScript (la classe du composant ou, plus généralement, n’importe quelle expression TypeScript) et de l’afficher dans la partie HTML. Elle s’utilise via la syntaxe {{expression}} dans le HTML :

courses.component.html
<p>interpolation : {{titre}} et {{3 + 4}}</p>
courses.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = 'liste de cours';
}

Si le template HTML du composant app est :

app.component.html
<h1>Ceci est mon composant App</h1>
<app-courses />
<app-courses />
<router-outlet />

on obtient l’affichage suivant :

Affichage avec l'interpolation

Notez que rien n’empêche de placer entre les doubles accolades des appels de méthode (comme je le disais, n’importe quelle expression peut être utilisée) :

courses.component.html
<p>interpolation : {{get_titre()}} et {{3 + 4}}</p>
courses.component.ts
import {Component, signal} from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = signal('liste de cours');

  get_titre(): string {
    return this.titre() + ' (dans methode)'
  }
}

Important : les signaux

Dans la version actuelle d’Angular, on peut toujours utiliser le code ci-dessus mais il n’est pas optimal en termes de performances. En effet, l’une des problématiques d’Angular est de détecter quand l’affichage doit être modifié. Ici, par exemple, si la valeur de la propriété titre change, il faut réafficher les deux dernières lignes de la page. Si l’on possédait un moyen d’avertir Angular de ce qui peut changer dans la page, cela lui simplifierait le travail et lui permettrait d’être plus « optimal ». C’est le but des signaux. Leur utilisation est très simple. Au lieu de définir directement titre = valeur;, on écrit titre = signal(valeur); et on importe signal du core d’Angular :

courses.component.ts
import {Component, signal} from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = signal('liste de cours');
}

Afin d’utiliser la valeur de la propriété titre, que ce soit dans l’interpolation du template HTML ou dans le TypeScript, on écrit titre() :

courses.component.html
<p>interpolation : {{titre()}} et {{3 + 4}}</p>

On voit donc qu’exploiter les signaux n’est pas compliqué. En plus, ce sont des wrappers très « light », donc on a tout intérêt à les utiliser. On peut modifier leurs valeurs avec deux méthodes set (pour affecter une nouvelle valeur) et update pour mettre à jour la valeur courante :

courses.component.ts
import {Component, signal} from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = signal('liste de cours');

  constructor() {
    // modifications du titre
    this.titre.set("toto");
    this.titre.update((val) => {return val.toUpperCase();});
  }
}

Un composant peut avoir un constructeur. Dans celui-ci, j’ai commencé par modifier titre en lui affectant la chaîne « toto ». Ensuite, j’ai appelé la méthode update qui prend une fonction ayant un seul argument (la valeur actuelle de la variable) et qui renvoie sa nouvelle valeur. Ici, j’ai utilisé la syntaxe des arrow functions que nous avions vue dans la séance précédente pour déclarer cette fonction.

Règle

Quand les variables, propriétés, attributs de vos classes TypeScript auront des interactions avec le template HTML, utilisez des signaux. Vos applications n’en seront que plus efficaces.

Le property binding

Dans l’exemple ci-dessus, on a transféré de l’information du TypeScript vers une partie de la page, un nœud du DOM. Il peut également être utile de la transférer vers un attribut, une propriété, d’une balise. C’est l’objectif du property binding. On l’utilise en encadrant le nom de la propriété en question avec des []. L’exemple suivant vous montre :

  1. comment contrôler l’affichage de la balise <h1> avec du property binding. Ici, lorsque l’attribut hide du TypeScript est égal à true, la propriété hidden de la balise <h1> est mis à true et cette balise n’est donc pas affichée. Si on modifie la valeur de l’attribut hide, celle de la propriété hidden de la balise <h1> sera mise à jour automatiquement.

  2. comment remplir automatiquement le contenu de la balise <input>. Ici, lors de l’initialisation du composant, la valeur de l’attribut val_input est transmise à la balise <input>. Là encore, si l’on modifie la valeur de val_input, celle de la balise <input> sera mise à jour.

courses.component.html
<h1 [hidden]="hide()">Titre caché</h1>
<p>interpolation : {{titre()}}</p>
<input [value]="val_input()">
courses.component.ts
import {Component, signal} from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = signal('liste de cours');
  hide = signal(true);
  val_input = signal('property binding');
}

Voilà ce que produit le code ci-dessus :

Affichage avec property binding

L'event binding

Jusqu’à maintenant, on est parti du TypeScript et on a transféré de l’information vers le template HTML. Avec l’event binding, on réalise des transferts dans l’autre sens. Pour l’utiliser, on utilise la syntaxe (nom_événement)="callback()". Lorsque l’événement arrive, on va appeler la méthode callback(). On peut aussi passer un paramètre à cette méthode. Dans ce cas, le paramètre s’appelle $event :

courses.component.html
<h1 [hidden]="hide()">Titre caché</h1>
<p>interpolation : {{titre()}}</p>
<input [value]="val_input()" (keyup)="changeTitre($event)">
<button (click)="changeH1()">Hide ou pas le h1</button>
courses.component.ts
import {Component, signal} from '@angular/core';

@Component({
  selector: 'app-courses',
  imports: [],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  titre = signal('liste de cours');
  hide = signal(true);
  val_input = signal('property binding')

  changeH1() : void {
    this.hide.update((val) => {return !val; });
  }

  changeTitre(event : KeyboardEvent) {
    this.titre.set(`touche : ${event.key}`)
  }
}

Ici, chaque fois que l’on clique sur le bouton, la méthode changeH1() de la classe CoursesComponent est appelée et elle change la valeur de hide (true devient false, false devient true), ce qui a pour effet d’alterner la visibilité de la balise <h1>. Lorsque l’on est en train d’éditer l’input, chaque fois que l’on relâche une touche, la chaîne affichée par interpolation est mise à jour et affiche la touche en question.

Affichage avec event binding

Le two-way binding

La syntaxe du two-way binding est un mix entre le property binding ([] pour aller du TypeScript vers le template HTML) et l’event binding (() pour aller du template HTML vers le TypeScript). Comme le two-way binding va dans les deux sens, on utilise la syntaxe [()]. Pour être précis, la syntaxe est la suivante : [(ngModel)]="nom_attribut". ngModel est un mot-clef d’Angular. nom_attribut est le nom d’un attribut de la classe TypeScript. Attention : cet attribut ne doit pas être un signal (cf. la ligne 13 ci-dessous). Par ailleurs, il faut penser à importer FormsModule (en principe, votre IDE devrait le faire pour vous).

courses.component.html
<p>interpolation : {{val_input}}</p>
<input [(ngModel)]="val_input">
<button (click)="changeVal()">Change</button>
courses.component.ts
import {Component, signal} from '@angular/core';
import {FormsModule} from '@angular/forms';

@Component({
  selector: 'app-courses',
  imports: [
    FormsModule
  ],
  templateUrl: './courses.component.html',
  styleUrl: './courses.component.scss'
})
export class CoursesComponent {
  val_input = 'property binding';

  changeVal() {
    this.val_input = 'XXXXX';
  }
}

Dans le code ci-dessus, l’input contient un two-way binding, ce qui signifie que toute modification dans le TypeScript de l’attribut val_input sera reporté automatiquement vers l’input et l’interpolation du paragraphe <p></p>. Par exemple, si on clique sur le bouton Change, cela exécutera la méthode changeVal(), donc du TypeScript, et l’input et l’interpolation seront mises à jour avec la chaîne « XXXXX ». C’est ce que l’on a fait avec le bouton du bas dans la figure ci-dessous. À l’inverse, chaque fois que l’utilisateur modifie l’input en tapant du texte dedans, la valeur de l’attribut val_input du TypeScript est mise à jour, ce qui a pour conséquence de modifier l’interpolation (cf. le haut de la figure ci-dessous).

Affichages avec two-way binding

Exercice 1 : Forum - page de login   

Mettez à jour la page de login de votre forum de manière à ce que les données du TypeScript soient synchronisées avec celles du template HTML.

Faites en sorte que le bouton de soumission/d’envoi affiche dans la console Javascript le login et le password saisis par l’utilisateur. Pour afficher la console, cliquez droit dans votre navigateur, ce qui vous permettra d’obtenir le menu déroulant suivant qui, lui-même, vous permettra de sélectionner l’inspecteur :

Menu déroulant après clic droit

L’affichage de votre navigateur sera scindé en 2 et vous aurez accès à la console :

Affichage de la console Javascript

Règle

Lorsque vous programmez en Javascript, TypeScript ou Angular, ouvrez systématiquement la console Javascript. Cela vous permettra :

  1. de débugguer en faisant des affichages dans la console;

  2. de voir des erreurs ou warnings qui ne sont pas forcément décelables facilement en regardant la page web affichée.

Exercice 2 : Forum - La navbar   

Dans votre frontend, rajoutez un nouveau composant navbar. Celui-ci contiendra la barre de navigation en haut des pages. Pour la créer, vous pouvez exploiter la classe navbar de la balise <nav> fournie par bootstrap, cf. :

https://getbootstrap.com/docs/5.3/components/navbar.

Comme vous pouvez le voir sur le forum de démonstration, la navbar est identique, quelle que soit la page du frontend. Pour l’insérer de manière automatique dans toutes les pages, il suffit donc d’inclure ce composant au début du fichier app.component.html. Faites-le et vérifiez que vous voyez bien votre barre de navigation. Supprimez la balise <h1></h1> que vous aviez placée dans ce fichier.

 
© C.G. 2007 - 2025