Appearance
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
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 actiontypescriptexport 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ètresort
, qui est probablement utilisé pour déterminer l'ordre dans lequel les utilisateurs doivent être récupérés.
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.typescriptexport 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 }) }) ) } }
tsimport { 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); }) ); } }
tsexport 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'actionGetUsersAction
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 utilisonscontext.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;
};
}