What is the best way to retrieve messages from a websocket server and display them on an Angular component

Currently, I am in the process of learning how to integrate live chat into an Angular project using Socket.IO. Following a tutorial that I stumbled upon, which can be found here.

Incorporating an input box within my component has allowed me to successfully send messages from the component to the server.

https://i.sstatic.net/p50Wn.png

The obstacle I'm facing now is figuring out how to use 'emit' to send the message back to the user and update the DOM accordingly.

Let me walk you through my code. Although the chat box does not currently have its own component, it will eventually. Below is the TypeScript code for where the chat box resides. Keep in mind this is part of creating a card game so you may come across references to decks and dealers.

import { Component, OnInit, OnDestroy } from '@angular/core';
import { DealerService } from '../services/dealer.service';
import { ChatService } from '../services/chat.service';

@Component({
  selector: 'app-blackjackgame',
  templateUrl: './blackjackgame.component.html',
  styleUrls: ['./blackjackgame.component.css']
})
export class BlackjackgameComponent implements OnInit, OnDestroy {

  constructor(private dealer: DealerService, private chat: ChatService) { }

  ngOnInit() {
    this.dealer.generateDeck();
    this.dealer.shuffle(5);
    this.chat.messages.subscribe(msg => {
      console.log(msg);
    });

  }

  // Sending a message
  sendMessage(message: string) {
    this.chat.sendMsg(message);
  }


  // Unsure if this is the correct approach
  updateMessages(message: string) {
    console.log('message was emitted: ' + message);
  }

  ngOnDestroy() {
    
  }

}

I utilize two main services, namely the chat service and WebSocket service.

The chat service is structured as follows:

import { Injectable } from '@angular/core';
import { WebsocketService } from './websocket.service';
import { Observable, Subject } from 'rxjs/Rx';

@Injectable()
export class ChatService {

  messages: Subject<any>;

  constructor(private wsService: WebsocketService) {
    this.messages = <Subject<any>>wsService
      .connect()
      .map((response: any): any => {
      return response;
    });
  }

  sendMsg(msg){
    this.messages.next(msg);
  }

}

As for the WebSocket service:

import { Injectable } from '@angular/core';
import * as io from 'socket.io-client';
import { Observable } from 'rxjs/Observable';
import * as Rx from 'rxjs/Rx';
import { environment } from '../../environments/environment';


@Injectable()
export class WebsocketService {

  private socket; 
  constructor() { }

  connect(): Rx.Subject<MessageEvent> {
    this.socket = io(environment.ws_url);

    const observable = new Observable(observer => {
      this.socket.on('message', (data) => {
        console.log('Received a message from websocket service');
        observer.next(data);
      });
      return () => {
        this.socket.disconnect();
      };
    });

    const observer = {
      next: (data: Object) => {
        this.socket.emit('message', JSON.stringify(data));
      }
    };

    return Rx.Subject.create(observer, observable);
  }

}

Lastly, there's a WebSocket server written in plain JavaScript. The snippet above provides an overview, but here is the complete code:

var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

io.on('connection', function(socket){
    console.log('Connection made');
    socket.on('chat message', function(msg){
        io.emit('chat message', msg);
    });
});

http.listen(5000, function(){
  console.log('listening on *:5000');
});

Essentially, my WebSocket server logs when receiving a message. My query pertains to sending information back in response and updating the DOM within the component based on the WebSocket-emitted messages. Any guidance would be immensely appreciated since I am relatively inexperienced with this technology.

Answer №1

After some brainstorming, I finally cracked the code. It turns out I was on the right track all along. I decided to develop a brand new chat component to enhance the user experience. Here's how I put it together:

Chatbox Component HTML

<div id="chatDisplay">
  <ul>
    <li *ngFor = "let msg of messages">{{msg}}</li>
  </ul>
</div>
<div id="chatInput">
  <input type="text" id="chatBox" #chatMessage>
  <button (click)="sendMessage(chatMessage.value)">Send Message</button>
</div>

Chatbox Component TypeScript

import { Component, OnInit, OnDestroy } from '@angular/core';
import { ChatService } from '../services/chat.service';
import { Observable, Subject } from 'rxjs/Rx';

@Component({
  selector: 'app-chatbox',
  templateUrl: './chatbox.component.html',
  styleUrls: ['./chatbox.component.css']
})
export class ChatboxComponent implements OnInit, OnDestroy {

  messages = [];
  constructor(private chat: ChatService) { }

  ngOnInit() {
    this.chat.messages.subscribe(msg => {
      this.messages.push(msg.text);
    });
  }

  sendMessage(message: string){
    this.chat.sendMsg(message);
  }

  ngOnDestroy() {
  }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error in Redirecting to Localhost

Recently, I developed an Angular App that interacts with the MS Graph API using MSAL. Initially, everything worked smoothly when running "ng serve" in Angular CLI. However, I encountered a problem when I packaged this Angular App with electron to deploy i ...

A window that pops up in Angular 2

I'm in the process of developing a popup window that requests login details when a button is clicked. Here's what my app.component looks like: import { Component } from '@angular/core'; @Component({ selector: 'my-app', ...

What is the method for obtaining the total row of an ngFor loop within an HTML file?

I am trying to figure out how to retrieve the total number of rows in an ngFor loop and display it above. Any suggestions? <p>Total row: "I need to display the number of rows here"</p> <table class="table" > &l ...

Error message: "Unable to emit an array with Angular

Within the DateRangeComponent, I am attempting to trigger an array emission to another component (ViewerComponent) upon button click using the EventEmitter and Output decorator. The DateRangeComponent contains a getData() method which utilizes the EventEm ...

Why is the format incorrect when the Angular 7 (Change)-Function on Input of type Date isn't functioning?

I am facing an issue with updating the date using key input and assigning the selected date to a property of my object. Below is the code I'm currently working with: <input type="date" [value]="dateTime()" (change)="setDate($event)"/> The dat ...

Send data to assembled Angular directives

Using a third-party directive "A" with inputs a1 and a2, I am looking to create a new directive "B" that acts as a facade for "A". The goal is to set specific values for "A" within "B" so that configuring the inputs each time "A" is used is not necessary. ...

What is the purpose of `{ _?:never }` in programming?

I've been going through some TypeScript code and I stumbled upon a question. In the following snippet: type LiteralUnion<T extends U, U extends Primitive> = | T | (U & { _?: never }); Can anyone explain what LiteralUnion does and clarif ...

What is the best way to retrieve the parameter of ng2-file-upload using endback?

I am attempting to retrieve a parameter using PHP in order to save it into a folder. However, my code is not working as expected. Here is the code snippet: Using the Ionic framework this.uploader.onBeforeUploadItem = (item: any) => { this.uploader ...

My router-outlet is malfunctioning when trying to display my component

I am currently diving into learning Angular 2 in order to revamp my personal website. However, I've encountered an issue where my application fails to load the component when I navigate to the appropriate route by clicking on the navigation bar. Insi ...

Display JSON data in a list format within an Angular application

Is there a way to display individual JSON data in a browser? app.components.ts import { Component } from '@angular/core'; import { Http } from '@angular/http' import { HttpClient } from '@angular/common/http'; import { Empl ...

the process of accessing information from a service in an Angular Typescript file

After making a POST request using Angular's HTTP client, the response data can be accessed within the service. However, is there a way to access this data in the app.component.ts file? I am able to retrieve the response data within the service, but I ...

Having trouble with errors when trying to implement react-router-v6 with typescript

Having trouble with my code and receiving the following error: "Argument of type 'HTMLElement | null' is not assignable to parameter of type 'Element | DocumentFragment'. Type 'null' is not assignable to type 'Element | ...

Error: The ng2-scrollreveal package could not be located

When attempting to utilize ng2-scrollreveal npm within my Angular2 application and following all the specified instructions, I encountered console errors: zone.js:1274 GET http://localhost:3000/ng2-scrollreveal 404 (Not Found) and (index):18 Error: Erro ...

An error occurs when attempting to access a property that does not exist on type 'never'. Why is this considered an error rather than a warning?

I am experiencing an issue with the following code snippet: let count: number | undefined | null = 10; count = null; let result: string | undefined | null = count?.toFixed(2); console.log(`Result: ${result}`); The error message I received is as follows: ...

Retrieve data from a table within an Angular component

Struggling with the ng2-smart-table library, I am facing challenges in passing values entered in the edit line to a custom component: Refer to the code snippet below for passing Maximum and Minimum Temperature values to the SmartTableEditorFunctionsCompon ...

Achieving JSON element sorting in the most effective way

https://i.stack.imgur.com/NQbdN.png Each array contains the following information: {{ id: 39, treaty_number: "qwe", insurant_name: "222", belonging_to_the_holding_company: "test", date_start: "2016-04-15", etc }} Is there a way to sort each array in asc ...

DataGrid parameters in Material UI are only considering the final value in the table

I am working with a Data Grid table containing user information, and I want to include a sub-menu of options in the last column that opens up a modal for each user. However, I am facing an issue where only the data from the final row in the table is being ...

Having trouble with clearInterval in React TypeScript?

I have been encountering issues with the clearInterval function in TypeScript for React. I am not sure why the interval is not being cleared. To address this problem, I defined a variable let interval_counter;, and used it as follows: interval_counter = ...

How can I access the parameter value for the tooltip callback function within echarts?

I am attempting to retrieve the value for this specific Apache EChart from within the callback function of the tooltip formatter. When I manually input the value, the formatting function operates correctly: formatter: (params:any) => `$ ${Math.round(pa ...

Stripe detects that no signatures match the expected payload

Currently working on setting up a checkout session using Stripe that triggers my webhook upon successful completion. The issue I am facing is an error message stating "error: No signatures found matching the expected signature for payload. Are you passing ...