Les nouveautés d'Angular 19 en 4 minutes

Angular 19 vient de sortir, et il y a beaucoup de nouveautés intéressantes : hydratation incrémentale, linkedSignal, l'API des ressources, et plein d'autres choses. Venez découvrir tout ça en moins de 4 minutes !

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

Utiliser des paramètres dans le routeur

Il est possible de passer des paramètres dans l'URL pour afficher des informations spécifiques. Par exemple, pour afficher le profil d'un utilisateur, nous pouvons passer l'identifiant de l'utilisateur dans l'URL. Avant tout, voici la structure de notre application :

plaintext
app/
|- app.component.ts
|- app.router.ts
|- app.config.ts
|- main.component.ts
|- other.component.ts
ts
import { Routes } from '@angular/router';
import {OtherComponent} from './other.component';
import {MainComponent} from './main.component';

export const routes: Routes = [
  { path: '', redirectTo: 'main', pathMatch: 'full' },
  { path: 'main', component: MainComponent },
  { path: 'other/:id', component: OtherComponent }
];

:id indique que nous pouvons avoir un identifiant.

ts
import {Component} from '@angular/core';
import {RouterOutlet, RouterLink} from '@angular/router';

@Component({
  selector: 'app-root',
  imports: [RouterOutlet, RouterLink],
  standalone: true,
  template: `
    <ul>
      <li><a [routerLink]="['/main']">main</a></li>
      <li><a [routerLink]="['/other', 1337]">other</a></li>
    </ul>
    <router-outlet></router-outlet>
  `
})
export class AppComponent {}

Nous avons deux liens, un pour main et un pour other. Le lien other a un paramètre 1337. Nous utilisons un tableau pour définir le lien. Pourquoi ? Il est plus simple de passer des paramètres avec un tableau que de manipuler des chaînes.

Récupérer le paramètre dans le composant

Admettons que nous avons un composant OtherComponent :

js
import { Component, OnInit, inject } from '@angular/core';
import {ActivatedRoute, Router} from '@angular/router';

@Component({
  selector: 'app-other',
  standalone: true,
  template: `
    Other with id {{id}}
    <button (click)="nav()">MainComponent</button>
  `
})
export class OtherComponent implements OnInit {
  private route = inject(ActivatedRoute);
  private router = inject(Router);
  id = 0;

  ngOnInit() {
    this.route.params.subscribe(params => {
       this.id = +params.id; // + permet de convertir la chaîne en nombre
    });
  }

  nav() {
    this.router.navigate(['/main']);
  }
}

Nous chargeons et initialisons le service ActivatedRoute. Nous récupérons le paramètre avec un Observable lorsque le composant est initialisé.

Pourquoi avoir utiliser uj observable ?

Les paramètres de route sont des observables. Cela signifie que nous pouvons les observer pour obtenir les valeurs. Cela nous permet de réagir aux changements de paramètres. Et ça peut être le cas ici ! Si nous changeons l'identifiant dans l'URL, le composant OtherComponent sera mis à jour.

Utiliser snapshot pour une valeur unique

Si vous n'avez pas besoin de réagir aux changements de paramètres, vous pouvez utiliser snapshot pour récupérer la valeur actuelle du paramètre :

ts
import { Component, inject } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

@Component({
  selector: 'app-other',
  standalone: true,
  template: `
    Other with id {{id}}
  `
})
export class OtherComponent {
  private route = inject(ActivatedRoute);
  id = this.route.snapshot.params['id'];
}

ATTENTION

snapshot ne réagira pas aux changements de paramètres. Si votre composant peut être réutilisé avec des paramètres différents (par exemple, naviguer de /user/1 vers /user/2), utilisez plutôt l'observable params comme montré précédemment.

CONSEIL

Utilisez snapshot quand :

  • Vous êtes certain que les paramètres ne changeront pas pendant la durée de vie du composant
  • Vous voulez une syntaxe plus simple et directe
  • Vous n'avez pas besoin de réagir aux changements de paramètres

Utiliser queryParamMap pour les paramètres de requête

Les paramètres de requête sont différents des paramètres de route. Ils apparaissent après le ? dans l'URL et permettent de filtrer ou trier des données sans changer de page. Par exemple : /users?sort=name&order=asc.

Imaginons que nous voulons afficher une liste d'utilisateurs avec la possibilité de les filtrer et de les trier :

ts
import { Component, inject, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../../core/services/user.service';
import { User } from './user.interface';

@Component({
  selector: 'app-user-list',
  standalone: true,
  template: `
    <div class="filters">
      <select (change)="onSort($event)">
        <option value="name">Trier par nom</option>
        <option value="email">Trier par email</option>
      </select>
      <input 
        type="text" 
        [value]="searchTerm" 
        (input)="onSearch($event)"
        placeholder="Rechercher..."
      >
    </div>

    @for (user of users; track user.id) {
      <div class="user-card">
        <h3>{{ user.name }}</h3>
        <p>{{ user.email }}</p>
      </div>
    }
  `
})
export class UserListComponent implements OnInit {
  private route = inject(ActivatedRoute);
  private router = inject(Router);
  private userService = inject(UserService);

  users: User[] = [];
  searchTerm = '';
  sortBy = 'name';

  ngOnInit() {
    // Observer les changements des paramètres de requête
    this.route.queryParamMap.subscribe(params => {
      this.searchTerm = params.get('search') || '';
      this.sortBy = params.get('sort') || 'name';
      this.loadUsers();
    });
  }

  onSearch(event: Event) {
    const value = (event.target as HTMLInputElement).value;
    this.updateQueryParams({ search: value });
  }

  onSort(event: Event) {
    const value = (event.target as HTMLSelectElement).value;
    this.updateQueryParams({ sort: value });
  }

  private updateQueryParams(params: { [key: string]: string }) {
    this.router.navigate([], {
      relativeTo: this.route,
      queryParams: params,
      queryParamsHandling: 'merge' // Garde les autres paramètres existants
    });
  }

  private loadUsers() {
    this.userService.getUsers({
      search: this.searchTerm,
      sort: this.sortBy
    }).subscribe(users => this.users = users);
  }
}

Analysons cette syntaxe de navigation :

typescript
this.router.navigate([], {
  relativeTo: this.route,
  queryParams: params,
  queryParamsHandling: 'merge'
});

Décomposons chaque partie :

  1. navigate([]) : Le tableau vide [] signifie que nous ne changeons pas de route, nous restons sur la même page

  2. relativeTo: this.route : Indique que nous voulons naviguer relativement à la route actuelle

  3. queryParams: params : Définit les nouveaux paramètres de requête à ajouter dans l'URL

  4. queryParamsHandling: 'merge' : Détermine comment gérer les paramètres existants

Exemple concret

Imaginons que nous sommes sur l'URL : /users?page=1&sort=name

Si nous exécutons :

typescript
this.router.navigate([], {
  relativeTo: this.route,
  queryParams: { search: 'john' },
  queryParamsHandling: 'merge'
});

L'URL deviendra : /users?page=1&sort=name&search=john

Sans merge, nous aurions perdu page et sort : /users?search=john

ATTENTION

Si vous omettez queryParamsHandling, tous les paramètres de requête existants seront supprimés et remplacés par les nouveaux. Utilisez 'merge' si vous voulez conserver les autres filtres actifs.

Avantages des Query Params

Les query params sont parfaits pour :

  • Filtrer des données
  • Trier des résultats
  • Gérer la pagination
  • Sauvegarder l'état de l'interface utilisateur
  • Partager des URLs avec des filtres spécifiques

Utiliser snapshot avec queryParamMap

Comme pour les params normaux, vous pouvez aussi utiliser snapshot pour les queryParams si vous n'avez pas besoin de réagir aux changements :

ts
export class SimpleUserListComponent {
  private route = inject(ActivatedRoute);
  
  // Récupération unique des query params
  searchTerm = this.route.snapshot.queryParamMap.get('search') || '';
  sortBy = this.route.snapshot.queryParamMap.get('sort') || 'name';
}

Préserver les queryParams lors de la navigation

Parfois, vous voulez garder les queryParams lors de la navigation vers une autre route. Vous pouvez le faire de deux façons :

ts
// Dans le template avec routerLink
<a [routerLink]="['/other-page']" [queryParamsHandling]="'preserve'">Autre page</a>

// Dans le component avec Router
this.router.navigate(['/other-page'], {
  queryParamsHandling: 'preserve'
});

Les options pour queryParamsHandling sont :

  • 'preserve' : garde tous les queryParams actuels
  • 'merge' : fusionne les nouveaux queryParams avec les existants

Chaque mois, recevez en avant-première notre newsletter avec les dernières actualités, tutoriels, astuces et ressources Angular directement par email !