Aller au contenu principal

3 - Websockets et Angular

Nous avons vu comment configurer le serveur pour accepter les requêtes en provenance de WebSockets et avons utilisé Postman pour tester quelques messages.

Cependant, ces messages viendront de Angular et ce dernier devra aussi être en mesure de recevoir des messages du serveur.

Installer ngx-socket-io

Dans un premier temps, nous installerons une librairie qui facilitera l'interaction avec les WebSockets en Angular, soit ngx-socket-io. On forcera la version 4.9.0, soit celle compatible avec Angular 20.

npm install ngx-socket-io@4.9.0

Configurer ngx-socket-io

  1. Dans app.config.ts, on doit ajouter la configuration, soit pour l'instant l'URL à contacter pour les WebSocket. On ajoute cette configuration dans le haut du fichier, juste après les imports.
    src/app/app.config.ts
    const config: SocketIoConfig = {
    url: 'http://localhost',
    options: {}
    };

    export const appConfig: ApplicationConfig = {
    // ...
  2. Au tableau providers dans app.config.ts, on ajoute provideSocketIo en utilisant la configuration créée plus haut.
    src/app/app.module.ts
    const config: SocketIoConfig = {
    url: 'http://localhost',
    options: {}
    };

    export const appConfig: ApplicationConfig = {
    providers: [
    provideBrowserGlobalErrorListeners(),
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    provideSocketIo(config)
    ]
    };

Envoyer un message à partir d'Angular

Pour envoyer un message via WebSocket à partir d'Angular, on le fait via la librairie Socket IO installée précédemment.

  1. Injectez Socket via le constructeur de votre composant

    src/app/pages/pixels/pixels.page.ts
    export class PixelsPage implements OnInit
    {
    grid: number[][] = [];

    constructor(private socket: Socket) {}

    //...
  2. Le fait j'injecter Socket fait en sorte de connecter automatiquement le client au serveur!

  3. Pour émettre un événement, il suffit d'appeler socket.emit avec le nom de l'événement et les données. Dans mon cas, l'appel se fait dans une fonction lorsque l'utilisateur appuie sur un carré de la grille pour ajouter un pixel au dessin.

    src/app/features/drawing/pages/pixels.ts
    draw(row: number, col: number) {
    this.socket.emit('pixel', {
    x: row,
    y: col,
    });
    }
    info

    pixel est le nom du message, c'est ce que nous avons configuré côté serveur. { x: row, y: col } ce sont les données (data). Elles doivent correspondre au dto côté serveur.

  4. Créons l'équivalent du DTO serveur, mais côté client, afin de typer adéquatement les données.

    src/core/requetes/creer-pixel-requete.ts
    export interface CreerPixelRequete {
    x: number;
    y: number;
    }
  5. Typons adéquatement l'envoi

    src/app/features/drawing/pages/pixels.ts
    draw(row: number, col: number) {
    const creerPixelRequete: CreerPixelRequete = {
    x: row,
    y: col,
    }
    this.socket.emit('pixel', creerPixelRequete)
    }

Observer et recevoir les messages

Pour recevoir les messages, il faut écouter le Socket et réagir lorsqu'un message est reçu.

  1. Enregistrez l'écoute dans ngOnInit et effectuez la tâche appropriée (ex.: ajouter le message à la liste de messages ou, dans mon cas, activer ou désactiver le pixel cliqué.)

    src/app/features/drawing/pages/pixels.ts
    ngOnInit(): void {
    //...

    this.socket.fromEvent('pixel').subscribe((data: any) => {
    this.grid[data.x][data.y] = this.grid[data.x][data.y] === 0 ? 1 : 0;
    });
    }
    info

    Ici, on utilise fromEvent avec le nom de l'événement auquel s'abonner. Dans notre cas, il s'agit de pixel. Cette fonction retourne un observable, c'est pourquoi on utilise ensuite subscribe, tout en passant une fonction anonyme qui sera exécutée à chaque événement reçu.

    Dans mon cas, j'active ou désactive le pixel qui a été sélectionné.

Se déconnecter du socket

Lorsque le composant est détruit, vous voudrez appeler la fonction disconnect() sur le socket.

src/app/pages/pixels/pixels.page.ts
ngOnDestroy(): void {
this.socket.disconnect();
}

img