//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