Preview:
//HTML
<div class="container" *ngIf="messages.length > 0">
  <table class="table table-striped table-hover align-middle">
    <thead class="table-dark">
      <tr>
        <th>#</th>
        <th>Type</th>
        <th>Message</th>
        <th>TimeStamp</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let item of messages; let i = index">
        <td>
          {{i + 1}}
        </td>
        <td>
          {{ item.type }}
        </td>
        <td>
          {{ item.message }}
        </td>
        <td>
          {{ item.dateTimeStamp }}
        </td>
      </tr>
    </tbody>
  </table>
</div>

<!-- Add your code above this point -->

<div id="assistant">
  <button id="assistant-popup-button" (click)="openSupportPopup()">
    Chat Support?
  </button>
  <div id="assistant-popup" [style.display]="isOpen ? 'block' : 'none'">
    <div id="assistant-popup-header">
      Your friendly Assistant
      <button id="assistant-popup-close-button" (click)="openSupportPopup()">
       X
      </button>
    </div>
    <div id="assistant-popup-body">
      <div class="messages" #scrollMe>
        <div *ngFor="let message of messages" class="message">
          <div [class]="message.type">
            {{ message.message }}
          </div>
        </div>
        <div
          *ngIf="loading"
          class="message"
          style="width: 100%; display: block"
        >
          <div [class]="'client'">...</div>
        </div>
      </div>
    </div>
    <form id="assistant-popup-footer" [formGroup]="chatForm">
      <input
        formControlName="message"
        type="text"
        id="assistant-popup-input"
        placeholder="Type your message here..."
      />
      <button
        id="assistant-popup-submit-button"
        [disabled]="!chatForm.valid"
        (click)="sendMessage()">
        Submit
      </button>
    </form>
  </div>
</div>

//TS
import { Component, ViewChild } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { MessageService } from '../service/api.service';
import { DatePipe } from '@angular/common';


export interface Message {
  //Type of the message (e.g., 'user' or 'client')
  type: string;
  //Content of the message
  message: string;
  //Timestamp of when the message was created
  dateTimeStamp: string;
}

@Component({
  selector: 'app-chat-support',       
  templateUrl: './chat-support.component.html',
  styleUrls: ['./chat-support.component.scss'],
})
export class ChatSupportComponent {
  // Indicates if the chat support popup is open
  isOpen = false;
  // Indicates if a message is being sent
  loading = false;
  // Holds the current date and time
  currentDateTime: any
  // Array to hold the chat messages
  messages: Message[] = [];
  chatForm = new FormGroup({
    // Form control for the message input with validation
    message: new FormControl('', [Validators.required]),
  });
  // Reference to the scroll container element
  @ViewChild('scrollMe') private myScrollContainer: any; 

  constructor(private messageService: MessageService, public datepipe: DatePipe) {
    // Constructor to inject necessary services
  }

  openSupportPopup() {
    // Toggles the chat support popup open or closed
    this.isOpen = !this.isOpen;
  }

  sendMessage() {
//Sends the user message and handles response from server
    this.currentDateTime = this.getDateTimeStamp(); // Get the current timestamp
    const sentMessage = this.chatForm.value.message!; // Get the message from the form
    this.loading = true; // Set loading to true while sending the message
    this.messages.push({
      type: 'user', // Mark the message as from the user
      message: sentMessage, // The message content
      dateTimeStamp: this.currentDateTime // Timestamp of the message
    });
    this.chatForm.reset(); // Reset the chat form
    this.scrollToBottom(); // Scroll to the bottom of the chat
    this.messageService.sendMessage(sentMessage).subscribe((response: any) => {
      // Subscribe to the response from the message service
      for (const obj of response) {
        let value;
        if (obj.hasOwnProperty('text')) {
          // Handle text messages
          value = obj['text'];
          this.pushMessage(value);
        }
        if (obj.hasOwnProperty('image')) {
          // Handle image messages
          value = obj['image'];
          this.pushMessage(value);
        }
      }
    });
  }

  pushMessage(message: string) {
    // Adds a client message to the messages array
    this.currentDateTime = this.getDateTimeStamp(); // Get the current timestamp
    this.messages.push({
      type: 'client', // Mark the message as from the client
      message: message, // The message content
      dateTimeStamp: this.currentDateTime // Timestamp of the message
    });
    this.scrollToBottom(); // Scroll to the bottom of the chat
  }

  getDateTimeStamp() {
// Returns current date and time as 'dd/MM/yyyy h:mm:ss'
    return this.datepipe.transform(new Date(), 'dd/MM/yyyy h:mm:ss');
  }

  scrollToBottom() {
    // Scrolls the chat to the bottom
    setTimeout(() => {
      try {
        this.myScrollContainer.nativeElement.scrollTop =
          this.myScrollContainer.nativeElement.scrollHeight + 500;
      } catch (err) {}
    }, 150);
  }
}
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter