🧭 Angular 21.1 — nouveautés & changements principaux

🧭 Angular 21.1 — nouveautés & changements principaux

LoĂŻc Boutter (lazybobcat)
LoĂŻc Boutter (lazybobcat)

Angular 21.1 est arrivé. Pas de révolution, mais une série de petites améliorations et de corrections.

Dans cet article, on fait le tour des nouveautés principales.

🎛️ Templates : plus expressifs, moins verbeux

@switch : plusieurs @case pour un seul bloc

Quand plusieurs @case doivent afficher la même chose, Angular 21.1 permet enfin d’éviter le copier-coller.

@switch (pokemon.status) {
  @case ('poisoned')
  @case ('paralyzed') {
    <app-status-badge kind="warning">Ouille…</app-status-badge>
  }
  @case ('fainted') {
    <app-status-badge kind="danger">K.O.</app-status-badge>
  }
  @default {
    <app-status-badge kind="ok">Tout va bien</app-status-badge>
  }
}

Spread operator ... dans les templates

Le spread est maintenant supporté dans les templates, y compris dans les appels de fonctions.

Exemple : composer une équipe et des stats affichées.

@let team = [starter, ...capturedPokemons];
 
<app-team [pokemons]="team" />
 
<app-stats [value]="{ ...baseStats, ...bonusStats }" />
 
<button (click)="battle(...team)">Combat !</button>

Note : c’est pratique pour de la composition simple. Si ça devient une usine à gaz, un computed() dans le composant évite de transformer le template en usine à gaz.

🧪 Signal Forms (expérimental) : ça se muscle

Signal Forms reste expérimental, mais 21.1 apporte plusieurs changements importants.

Renommage [field] → [formField]

Le selector [field] était trop générique et des collisions avec d’autres packages ou avec des codebase ont fait surface. Il a donc été renommé en [formField].

<!-- avant -->
<input [field]="pokemonForm.name" />
 
<!-- après -->
<input [formField]="pokemonForm.name" />

Si vous aviez déjà adopté Signal Forms, c’est la migration la plus visible.

Renommage field → fieldTree (validations)

De la même manière et si vous avez créé des validateurs custom, vérifiez les interfaces d’erreur.

// avant
const error: ValidationError = {
  field: context.fieldTree.name,
  kind: 'pokemon-name-required',
  message: 'Le nom du Pokémon est obligatoire'
};
 
// après
const error: ValidationError = {
  fieldTree: context.fieldTree.name,
  kind: 'pokemon-name-required',
  message: 'Le nom du Pokémon est obligatoire'
};

Nouveau : classes CSS automatiques

On peut configurer des classes CSS en fonction de l’état d’un champ (un peu comme ng-valid, ng-touched, etc.).

Exemple : ajouter une classe quand le champ est invalide et touché.

provideSignalFormsConfig({
  classes: {
    'is-invalid': field => field.state().invalid() && field.state().touched(),
  }
});

Pratique si vous utilisez Bootstrap/Tailwind, ou si vous voulez un style particulier sur plus qu’un champ de formulaire.

đź§­ Router : un peu plus signal

isActive() standalone (signal) + dépréciation de Router.isActive()

Le router fournit désormais un signal isActive().

Exemple : activer un onglet “Pokédex” si l’URL correspond.

import { Component, inject } from '@angular/core';
import { Router, isActive } from '@angular/router';
 
@Component({
  // ...
  template: `
    <a [class.active]="isPokedexActive()" routerLink="/pokedex">Pokédex</a>
  `
})
export class NavComponent {
  private router = inject(Router);
  isPokedexActive = isActive('/pokedex', this.router, {
    paths: 'subset',
    queryParams: 'ignored',
    fragment: 'ignored',
    matrixParams: 'ignored'
  });
}

Expérimental : cleanup automatique des injectors de routes

Depuis la version 21, on peut injecter des services dans les routes. Cependant, ils ne sont pas nettoyés lorsque l’on change de page. Angular 21.1 ajoute un nouveau mode qui nettoie automatiquement les services injectés “périmés” lors de la navigation :

provideRouter(routes, withExperimentalAutoCleanupInjectors());

Cela évite les problèmes de fuites de mémoire.

Expérimental : intégration avec la Navigation API

Le router peut aussi s’intégrer expérimentalement à la Navigation API (standard navigateur). L’idée : mieux s’aligner sur la navigation “native” (restauration du scroll/focus, interceptions plus robustes, etc.).

provideRouter(routes, withExperimentalPlatformNavigation());

đź§Ż SSR/Hydration : provideStabilityDebugging()

Quand une app SSR/hydratée ne “stabilise” pas, le debug peut vite ressembler à chercher Mew sous un camion.

Angular 21.1 ajoute provideStabilityDebugging() qui log des informations de débogage si l’app n’est toujours pas stable après 9 secondes.

bootstrapApplication(AppComponent, {
  providers: [provideStabilityDebugging()],
});

🤖 AI / MCP : l’outillage continue d’évoluer

Angular continue d’investir sur son serveur MCP (expérimental) pour piloter build/devserver/tests/e2e via des outils. Si vous testez des assistants IA, ça peut faciliter la vie.

Pour en savoir plus

Retour aux articles