Preview:
//chat-support component
//HTML
<div id="assistant">
  // Button to open the chat support popup
  <button id="assistant-popup-button" (click)="openSupportPopup()">
    Chat Support?
  </button>
  
  // Popup container for chat support, visibility controlled by isOpen property
  <div id="assistant-popup" [style.display]="isOpen ? 'block' : 'none'">
    
    // Header section of the popup with a close button
    <div id="assistant-popup-header">
      Your friendly Assistant
      
      // Button to close the chat support popup
      <button id="assistant-popup-close-button" (click)="openSupportPopup()">
       X
      </button>
    </div>
    
    // Body of the popup containing chat messages
    <div id="assistant-popup-body">
      <div class="messages" #scrollMe>
        
        // Loop through messages array to display each message
        <div *ngFor="let message of messages" class="message">
          // Display message with a specific class based on message type
          <div [class]="message.type">
            {{ message.message }}
          </div>
        </div>
        
        // Display a loading indicator if messages are being loaded
        <div
          *ngIf="loading"
          class="message"
          style="width: 100%; display: block"
        >
          <div [class]="'client'">...</div>
        </div>
      </div>
    </div>
    
    // Footer of the popup containing the input form for new messages
    <form id="assistant-popup-footer" [formGroup]="chatForm">
      // Input field for typing new messages, bound to chatForm control
      <input
        formControlName="message"
        type="text"
        id="assistant-popup-input"
        placeholder="Type your message here..."
      />
      
      // Submit button for sending new messages, disabled if form is invalid
      <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';

export interface Message {
  type: string;
  message: string;
}

@Component({
  selector: 'app-chat-support',
  templateUrl: './chat-support.component.html',
  styleUrls: ['./chat-support.component.scss'],
})
export class ChatSupportComponent {
  isOpen = false; //Variable to toggle chat interface visibility
  loading = false; //Indicates if a message is being sent/loading
  messages: Message[] = []; //Array to store chat messages
  chatForm = new FormGroup({
    message: new FormControl('', [Validators.required]), // Input field for user message
  });
  @ViewChild('scrollMe') private myScrollContainer: any;

  constructor(private messageService: MessageService) {
  }
  // Function to open or close the chat interface
  openSupportPopup() {
    this.isOpen = !this.isOpen;
  }
  // Function to send a user message to the Rasa chatbot
  sendMessage() {
    const sentMessage = this.chatForm.value.message!;
    this.loading = true;
    // Add user message to the messages array
    this.messages.push({
      type: 'user',
      message: sentMessage,
    });
    this.chatForm.reset();
    this.scrollToBottom();
    
 //Send user message to Rasa chatbot backend via messageService
    this.messageService.sendMessage(sentMessage).subscribe((response: any) => {
      for (const obj of response) {
        let value
        // Check if the response has a 'text' property
        if (obj.hasOwnProperty('text') ) {
          value = obj['text']
          this.pushMessage(value) //Add the text response to the messages array

        }
        // Check if the response has an 'image' property
        if (obj.hasOwnProperty('image') ) {
          value = obj['image']
          this.pushMessage(value) //Add the image response to the messages array
        }
      }
    });
  }

//Function to add a client message (bot response) to the messages array
  pushMessage(message:string){
     this.messages.push({
        type: 'client',
        message: message,
      });
      this.scrollToBottom();//Scroll to the bottom of the chat container
  }

  //Function to scroll to the bottom of the chat container
  scrollToBottom() {
    setTimeout(() => {
      try {
 // Set the scrollTop property to the maximum scroll height
        this.myScrollContainer.nativeElement.scrollTop =
          this.myScrollContainer.nativeElement.scrollHeight + 500;
      } catch (err) {}
    }, 150);
  }
}

//SCSS
@import url("https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap");
#assistant {
  font-family: "Roboto", sans-serif;
  #assistant-popup-button {
    position: fixed;
    bottom: 20px;
    right: 20px;
    padding: 10px 20px;
    background-color: #333;
    color: #ffffff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    font-size: 14px;
    z-index: 1000;
  }

  #assistant-popup {
    position: fixed;
    bottom: 40px;
    right: 20px;
    width: 450px;
    height: 50vh;
    min-height: 450px;
    background-color: white;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
    border-radius: 5px;
    z-index: 1000;
    display: none;
    #assistant-popup-header {
      background-color: #333;
      color: white;
      font-size: 18px;
      padding: 10px;
      border-top-left-radius: 5px;
      border-top-right-radius: 5px;
      #assistant-popup-close-button {
        float: right;
        border: none;
        background-color: transparent;
        color: #fff;
        font-size: 14px;
        cursor: pointer;
      }
    }

    #assistant-popup-body {
      height: calc(100% - 133px);
      padding: 10px;
    }

    #assistant-popup-footer {
      background-color: #333;
      color: white;
      font-size: 14px;
      padding: 10px;
      border-bottom-left-radius: 5px;
      border-bottom-right-radius: 5px;
      #assistant-popup-input {
        width: 100%;
        padding: 10px;
        border: 1px solid #fff;
        border-radius: 5px 5px 0 0;
        box-sizing: border-box;
        font-size: 14px;
      }

      #assistant-popup-submit-button {
        width: 100%;
        padding: 10px;
        background-color: #2ca1da;
        color: #fff;
        border: none;
        border-radius: 0 0 5px 5px;
        cursor: pointer;
        font-size: 14px;
      }
    }

    .messages {
      height: 100%;
      overflow: auto;
      .message {
        display: flow-root;
        width: 100%;
        .client {
          background-color: #d7d7d7;
          color: #333;
          padding: 10px;
          border-radius: 5px;
          margin-bottom: 10px;
          display: inline-block;
          max-width: 80%;
        }

        .user {
          border: 0.5px solid #333;
          background-color: #85ff7a;
          color: #333;
          padding: 10px;
          border-radius: 5px;
          margin-bottom: 10px;
          display: inline-block;
          max-width: 80%;
          text-align: right;
          float: right;
        }
      }
    }
  }
}


//API service
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class MessageService {
  constructor(private http: HttpClient) {}
  
// Function to send a message to the Rasa chatbot backend
  sendMessage(message: string) {
//Make a POST request to the Rasa chatbot webhook endpoint
    return this.http.post('http://localhost:5005/webhooks/rest/webhook', { message: message });
  }
}

//APP component
//HTML
<router-outlet></router-outlet>
<app-chat-support></app-chat-support>

//Module ts
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ChatSupportComponent } from './assistant/chat-support.component'

@NgModule({
  declarations: [AppComponent, ChatSupportComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    FormsModule,
    ReactiveFormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}
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