//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 {}
Preview:
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