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;
    };
}