Skip to content

Formulaires

Fanny Saez edited this page Jul 18, 2026 · 3 revisions

Formulaires

Angular propose deux approches pour gérer les formulaires : les formulaires template-driven (pilotés depuis le template, avec ngModel) et les formulaires réactifs (pilotés depuis la classe TypeScript, avec FormGroup/FormControl). Cette page couvre les deux, avec cours, exemple et exercice pour chacune des 4 leçons.

Prérequis : avoir lu les pages Composants et Routage.

C'est quoi, à quoi ça sert, pourquoi ?

  • C'est quoi ? Un ensemble d'outils Angular (ngModel, FormGroup/FormControl, validateurs) pour lier des champs de saisie HTML à des données de la classe du composant.
  • À quoi ça sert ? À récupérer, contrôler et valider ce que l'utilisateur saisit (connexion, inscription, recherche, contact...) avant de l'utiliser ou de l'envoyer à une API.
  • Pourquoi ? Presque toute application interagit avec l'utilisateur via des formulaires. Sans validation ni gestion propre des saisies, on s'expose à des données incorrectes ou incomplètes envoyées au serveur.

Sommaire

  1. Formulaires
  2. Obtention des valeurs de contrôle de formulaire
  3. Formulaires réactifs
  4. Validation des formulaires

1. Formulaires

Cours

L'approche la plus simple pour créer un formulaire consiste à utiliser le module FormsModule et la directive ngModel, qui crée une liaison bidirectionnelle (two-way binding) entre un champ de saisie et une propriété de la classe : la propriété se met à jour quand l'utilisateur tape, et le champ se met à jour si la propriété change dans le code.

La syntaxe [(ngModel)]="propriete" (surnommée "banana in a box") combine property binding ([ngModel]) et event binding ((ngModelChange)).

Exemple

import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-profil-form',
  imports: [FormsModule],
  template: `
    <label>
      Nom :
      <input [(ngModel)]="nom" name="nom">
    </label>
    <p>Bonjour, {{ nom() }} !</p>
  `,
})
export class ProfilForm {
  nom = signal('');
}

Note : à partir d'Angular récent, [(ngModel)] fonctionne directement avec des signal(). Chaque <input> utilisant ngModel dans un <form> doit avoir un attribut name.

Exercice

Crée un composant FormulaireContact avec un champ nom et un champ email, tous deux liés via [(ngModel)] à des signaux. Affiche un résumé "Nom : ... / Email : ..." qui se met à jour en temps réel.

Solution
import { Component, signal } from '@angular/core';
import { FormsModule } from '@angular/forms';

@Component({
  selector: 'app-formulaire-contact',
  imports: [FormsModule],
  template: `
    <label>Nom : <input [(ngModel)]="nom" name="nom"></label>
    <label>Email : <input [(ngModel)]="email" name="email"></label>
    <p>Nom : {{ nom() }} / Email : {{ email() }}</p>
  `,
})
export class FormulaireContact {
  nom = signal('');
  email = signal('');
}

2. Obtention des valeurs de contrôle de formulaire

Cours

Il n'est pas toujours nécessaire d'utiliser ngModel. On peut aussi récupérer la valeur d'un champ directement depuis l'événement DOM, avec un event binding classique (input) ou (change), et $event.target. C'est une approche plus proche du HTML natif, utile pour des formulaires simples ou ponctuels.

Exemple

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

@Component({
  selector: 'app-recherche-produit',
  template: `
    <input (input)="onSaisie($event)" placeholder="Nom du produit">
    <p>Vous cherchez : {{ recherche() }}</p>
  `,
})
export class RechercheProduit {
  recherche = signal('');

  onSaisie(event: Event) {
    const valeur = (event.target as HTMLInputElement).value;
    this.recherche.set(valeur);
  }
}

Exercice

Crée un composant CalculateurAge avec un <input type="number"> pour l'année de naissance. À chaque saisie, calcule et affiche l'âge approximatif (année courante moins année saisie), sans utiliser ngModel.

Solution
import { Component, signal } from '@angular/core';

@Component({
  selector: 'app-calculateur-age',
  template: `
    <input type="number" (input)="onSaisie($event)" placeholder="Année de naissance">
    <p>Âge approximatif : {{ age() }} ans</p>
  `,
})
export class CalculateurAge {
  age = signal(0);

  onSaisie(event: Event) {
    const anneeNaissance = Number((event.target as HTMLInputElement).value);
    const anneeActuelle = new Date().getFullYear();
    this.age.set(anneeActuelle - anneeNaissance);
  }
}

3. Formulaires réactifs

Cours

Les formulaires réactifs (module ReactiveFormsModule) déplacent la logique du formulaire dans la classe TypeScript plutôt que dans le template. On modélise le formulaire avec un FormGroup composé de FormControl, ce qui offre un typage fort, une meilleure testabilité et davantage de contrôle — recommandé pour des formulaires complexes.

Exemple

import { Component } from '@angular/core';
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-inscription',
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="formulaire" (ngSubmit)="onSoumission()">
      <input formControlName="nom" placeholder="Nom">
      <input formControlName="email" placeholder="Email">
      <button type="submit">S'inscrire</button>
    </form>
  `,
})
export class Inscription {
  formulaire = new FormGroup({
    nom: new FormControl(''),
    email: new FormControl(''),
  });

  onSoumission() {
    console.log(this.formulaire.value);
  }
}

Exercice

Crée un FormGroup nommé formulaireLogin avec deux FormControl : identifiant et motDePasse. Construis le template avec formGroup, formControlName et un bouton de soumission qui affiche this.formulaireLogin.value dans la console.

Solution
import { Component } from '@angular/core';
import { FormGroup, FormControl, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-login',
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="formulaireLogin" (ngSubmit)="onSoumission()">
      <input formControlName="identifiant" placeholder="Identifiant">
      <input formControlName="motDePasse" type="password" placeholder="Mot de passe">
      <button type="submit">Se connecter</button>
    </form>
  `,
})
export class Login {
  formulaireLogin = new FormGroup({
    identifiant: new FormControl(''),
    motDePasse: new FormControl(''),
  });

  onSoumission() {
    console.log(this.formulaireLogin.value);
  }
}

4. Validation des formulaires

Cours

Angular fournit des validateurs intégrés (Validators.required, Validators.email, Validators.minLength, etc.) qu'on associe à un FormControl. L'état du formulaire (valid, invalid, touched, dirty) permet d'afficher des messages d'erreur ciblés et de désactiver la soumission tant que le formulaire n'est pas valide.

Exemple

import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-inscription',
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="formulaire" (ngSubmit)="onSoumission()">
      <input formControlName="email" placeholder="Email">
      @if (formulaire.controls.email.invalid && formulaire.controls.email.touched) {
        <p class="erreur">Email invalide ou manquant.</p>
      }
      <button type="submit" [disabled]="formulaire.invalid">S'inscrire</button>
    </form>
  `,
})
export class Inscription {
  formulaire = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email]),
  });

  onSoumission() {
    if (this.formulaire.valid) {
      console.log(this.formulaire.value);
    }
  }
}

Exercice

Reprends le formulaireLogin de l'exercice précédent et ajoute des validateurs : identifiant obligatoire avec une longueur minimale de 3 caractères, motDePasse obligatoire avec une longueur minimale de 8 caractères. Affiche un message d'erreur sous chaque champ invalide et touché, et désactive le bouton de soumission tant que le formulaire est invalide.

Solution
import { Component } from '@angular/core';
import { FormGroup, FormControl, Validators, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'app-login',
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="formulaireLogin" (ngSubmit)="onSoumission()">
      <input formControlName="identifiant" placeholder="Identifiant">
      @if (formulaireLogin.controls.identifiant.invalid && formulaireLogin.controls.identifiant.touched) {
        <p class="erreur">L'identifiant doit contenir au moins 3 caractères.</p>
      }

      <input formControlName="motDePasse" type="password" placeholder="Mot de passe">
      @if (formulaireLogin.controls.motDePasse.invalid && formulaireLogin.controls.motDePasse.touched) {
        <p class="erreur">Le mot de passe doit contenir au moins 8 caractères.</p>
      }

      <button type="submit" [disabled]="formulaireLogin.invalid">Se connecter</button>
    </form>
  `,
})
export class Login {
  formulaireLogin = new FormGroup({
    identifiant: new FormControl('', [Validators.required, Validators.minLength(3)]),
    motDePasse: new FormControl('', [Validators.required, Validators.minLength(8)]),
  });

  onSoumission() {
    if (this.formulaireLogin.valid) {
      console.log(this.formulaireLogin.value);
    }
  }
}

Précédent : Routage     Suivant : Services

Apprendre Angular

Accueil

Démarrage

Le tutoriel (25 leçons)

Clone this wiki locally