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.

Créer l'action avec NgXs

L'action déclenche la récupération de la liste des utilisateurs. Dans ce tutoriel, nous allons approfondir le processus de création de cette action.

Création d'une action avec NgXS

  1. Définir la classe d'action:

    Chaque action dans NgXS est généralement représentée par une classe. Cela permet une grande flexibilité en termes de passage de données lors de la distribution d'une action.

    Dans src/app/store/users/users.action.ts, mettez cette action

    typescript
    export class GetUsersAction {
        static readonly type = '[Users] Get Users';
        constructor(public sort?: string) {}
    }
    • type: C'est une chaîne unique qui identifie l'action. Il est recommandé d'utiliser un format conventionnel tel que [Category] Action Description pour faciliter le débogage.
    • constructor: Dans cet exemple, notre action accepte un paramètre sort, qui est probablement utilisé pour déterminer l'ordre dans lequel les utilisateurs doivent être récupérés.
  2. Traiter l'action dans l'état:

    Une fois que nous avons notre action définie, nous devons l'associer à une méthode dans notre état (UserState), afin de définir ce qui doit se passer lorsqu'elle est déclenchée.

    typescript
    export class UserState {
         private userService = inject(UserService)
    
        @Action(GetUsersAction)
        getUsers(context: StateContext<UserStateModel>, action: GetUsersAction): Observable<any> {
            console.log('Trie possible par ', action.sort)
            return this.userService.getAll()
                .pipe(
                    tap((users: User[]) => {
                        context.patchState({
                            usersList: users
                        })
                    })
                )
        }
    }
    ts
    import { HttpClient } from "@angular/common/http";
    import { Injectable, inject, signal } from "@angular/core";
    import { Observable, tap } from "rxjs";
    import { User } from "../interfaces/user";
    
    @Injectable({
      providedIn: "root",
    })
    export class UserService {
      private http = inject(HttpClient);
      readonly url: string = "https://jsonplaceholder.typicode.com/users";
      users = signal<User[]>([]);
    
      getAll(): Observable<User[]> {
        return this.http.get<User[]>(this.url).pipe(
          tap((users) => {
            this.users.set(users);
          })
        );
      }
    }
    ts
    export interface User {
        id: number;
        name: string;
        username?: string;
        email: string;
        address?: {
            street: string;
            suite: string;
            city: string;
            zipcode: string;
            geo: {
                lat: string;
                lng: string;
            }
        };
        phone?: string;
        website?: string;
        company?: {
            name: string;
            catchPhrase: string;
            bs: string;
        };
    }

    L'annotation @Action indique à NgXS que la méthode qui suit doit être exécutée lorsque l'action GetUsersAction est déclenchée.

    Dans la méthode getUsers, nous faisons appel à userService.getAll() pour récupérer la liste des utilisateurs. Une fois que nous recevons ces données, nous utilisons context.patchState pour mettre à jour notre état.

    La méthode patchState est utile car elle nous permet de fusionner les nouvelles données avec l'état existant, sans avoir à fournir tout l'état à nouveau.

Déclencher l'action

Pour déclencher cette action dans un composant ou un autre service, vous utiliseriez le Store fourni par NgXS:

typescript
 import { Component, OnInit, inject } from '@angular/core';
 import { Store } from '@ngxs/store';
 import { Observable } from 'rxjs';
 import { User } from 'src/app/core/interfaces/user';
 import { GetUsersAction } from 'src/app/store/users/users.action.';

 @Component({
 selector: 'app-users',
 standalone: true,
 template: `
     @let users = usersList$ | async; <!-- depuis Angular 18.1 -->

     @if (users) {
         <ul>
             @for (user of users ; track user.id) {
                 <li>{{ user.name }}</li>
             }
         </ul>
     }
  `,
 })
 export class UsersComponent implements OnInit {
     private store = inject(Store)
     users$: Observable<User[]> = this.store.select(state => state.users.usersList);

     ngOnInit() {
         // Déclenchement de l'action pour charger les utilisateurs.
         this.store.dispatch(new GetUsersAction('someSortParameter')); // Remplacez 'someSortParameter' par le critère de tri souhaité.
     }
 }

Code en entier

ts
import { Injectable, inject } from "@angular/core";
import { Action, State, StateContext } from "@ngxs/store";
import { Observable, tap } from "rxjs";
import { User } from "src/app/core/interfaces/user";
import { UserService } from "src/app/core/services/user.service";
import { GetUsersAction } from "./users.action";

export interface UserStateModel {
    usersList: User[]
}

@State({
    name: 'users',
    defaults: {
        usersList: []
    }
})
@Injectable()
export class UserState {
    private userService = inject(UserService)

    @Action(GetUsersAction)
    getUsers(context: StateContext<UserStateModel>, action: GetUsersAction): Observable<any> {
        return this.userService.getAll(action.sort)
            .pipe(
                tap((users: User[]) => {
                    context.patchState({
                        usersList: users
                    })
                })
            )
    }
}
ts
export class GetUsersAction {
    static readonly type = '[Users] Get Users';
    constructor(public sort: string) {}
}
ts
import { HttpClient } from "@angular/common/http";
import { Injectable, inject } from "@angular/core";
import { Observable } from "rxjs";
import { User } from "./user";

@Injectable({
  providedIn: "root",
})
export class UserService {
  private http = inject(HttpClient);
  readonly url: string = "https://jsonplaceholder.typicode.com/users";

  getAll(): Observable<User[]> {
    return this.http.get<User[]>(this.url);
  }
}
ts
export interface User {
    id: number;
    name: string;
    username?: string;
    email: string;
    address?: {
        street: string;
        suite: string;
        city: string;
        zipcode: string;
        geo: {
            lat: string;
            lng: string;
        }
    };
    phone?: string;
    website?: string;
    company?: {
        name: string;
        catchPhrase: string;
        bs: string;
    };
}

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