Skip to content

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) {}
    }
    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 {
        constructor(
            private userService: 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
                        })
                    })
                )
        }
    }
    export class UserState {
        constructor(
            private userService: 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 } from "@angular/core";
    import { Observable } from "rxjs";
    import { User } from "src/app/core/interfaces/user";
    
    @Injectable({
        providedIn: 'root'
    })
    export class UserService {
        readonly url: string = 'https://jsonplaceholder.typicode.com/users'
    
        constructor(
            private http: HttpClient
        ) {}
    
        getAll(): Observable<User[]> {
            return this.http.get<User[]>(this.url)
        }
    }
    import { HttpClient } from "@angular/common/http";
    import { Injectable } from "@angular/core";
    import { Observable } from "rxjs";
    import { User } from "src/app/core/interfaces/user";
    
    @Injectable({
        providedIn: 'root'
    })
    export class UserService {
        readonly url: string = 'https://jsonplaceholder.typicode.com/users'
    
        constructor(
            private http: HttpClient
        ) {}
    
        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;
        };
    }
    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 } from '@angular/core';
 import { Store, Select } 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',
 template: `
     <div *ngIf="usersList$ | async as users">
     <h2>Liste des utilisateurs</h2>
     <ul>
         <li *ngFor="let user of users">{{ user.name }}</li>
     </ul>
     </div>
 `,
 })
 export class UsersComponent implements OnInit {
     @Select(state => state.users.usersList) usersList$: Observable<User[]>;

     constructor(private store: Store) {}

     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é.
     }
 }
import { Component, OnInit } from '@angular/core';
 import { Store, Select } 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',
 template: `
     <div *ngIf="usersList$ | async as users">
     <h2>Liste des utilisateurs</h2>
     <ul>
         <li *ngFor="let user of users">{{ user.name }}</li>
     </ul>
     </div>
 `,
 })
 export class UsersComponent implements OnInit {
     @Select(state => state.users.usersList) usersList$: Observable<User[]>;

     constructor(private store: Store) {}

     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 } 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 {
    constructor(
        private userService: 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
                    })
                })
            )
    }
}
import { Injectable } 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 {
    constructor(
        private userService: 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) {}
}
export class GetUsersAction {
    static readonly type = '[Users] Get Users';
    constructor(public sort: string) {}
}
ts
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { User } from "src/app/core/interfaces/user";

@Injectable({
    providedIn: 'root'
})
export class UserService {
    readonly url: string = 'https://jsonplaceholder.typicode.com/users'

    constructor(
        private http: HttpClient
    ) {}

    getAll(): Observable<User[]> {
        return this.http.get<User[]>(this.url)
    }
}
import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { User } from "src/app/core/interfaces/user";

@Injectable({
    providedIn: 'root'
})
export class UserService {
    readonly url: string = 'https://jsonplaceholder.typicode.com/users'

    constructor(
        private http: HttpClient
    ) {}

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