Azure Communication Service Chat Integration with Angular 13

Introduction

In this article we're going to look at Azure Communication Services with integrated angular applications. When you need to interact with your clients, friends, or colleagues, you need applications that enable you to chat from Azure Communication Services. Azure Communication Services provides some collection of APIs in Azure that you can use to chat, send and receive SMS messages, make video and audio calls, and place and receive telephone calls. Here we are going to see chat only. 

Create Azure Communication Service 

If you want to follow along, you'll need the following: 

  • An Azure subscription. If you don't have an Azure subscription, create a free account before you start. 

To create an Azure Communication Services resource, after signing in to the Azure portal. In the upper-left corner of the page, select -> + Create a resource

Enter text "Communication" into the search bar at the top of the portal. 

Learn about Azure Communication Service Chat Integrated Angular 13.

Once I get the search result select the Communication Services, select the result, and click Create. You can now configure your Communication Services resource. 

After you have selected the subscription and the resource group you can create a new one or select an existing resource group. 

Add Instance Details for Resource Name and Data location. Once entered all the details please click Review + Create and Created. Here I have referred to the resource name TestSatAzureTips

Learn about Azure Communication Service Chat Integrated Angular 13.

To manage your Communication Services resources, go to the Azure portal, and search for and select Azure Communication Services. On the Communication Services page, select the name of your resource. 

Learn about Azure Communication Service Chat Integrated Angular 13.

To manage your Communication Services resources, go to the Azure portal, and search for and select Azure Communication Services. On the Communication Services page, select the name of your resource. 

Learn about Azure Communication Service Chat Integrated Angular 13.

After navigating to your Communication Services resource, select Keys from the navigation menu and copy the Connection string or Endpoint values for usage by the Communication Services SDKs. 

Learn about Azure Communication Service Chat Integrated Angular 13.

If we need to see the keys, please click the show values icons. You can also access key information using Azure CLI, like your resource group or the keys for a specific resource. 

Before installing nodejs and angular CLI with basic project setup and then follow the below codes. Azure Communication Chat client library for angular. Please follow and install the libraries in an angular application.  

npm install @azure/communication-common --save 
npm install @azure/communication-identity --save 
npm install @azure/communication-signaling --save 
npm install @azure/communication-chat --save 

After installing the packages. here I have created two new components azure-chat.component.ts,  azure-chat. component.html and chat-thread.component.ts, chat-thread.component.html and copy the codes below. 

azure-chat.component.ts 

import {
    Component,
    OnInit
} from '@angular/core';
import {
    ChatClient,
    ChatThreadClient
} from '@azure/communication-chat';
import {
    HttpClient
} from '@angular/common/http';
import {
    AzureCommunicationTokenCredential
} from '@azure/communication-common';
import {
    CommunicationIdentityClient
} from '@azure/communication-identity';
@Component({
    selector: 'app-azure-chat',
    templateUrl: './azure-chat.component.html',
    // styleUrls: ['./azure-chat.component.css'] 
})
export class AzureChatComponent implements OnInit {
    endpointUrl = 'https://xxxxx.communication.azure.com';
    communicationUserId: string = '';
    userAccessToken: string = '';
    chatClient: ChatClient | any = null;
    Name: string = '';
    display_name: string = '';
    threadLink: string = '';
    chatThreadClient: ChatThreadClient | any = null;
    other_user_CommunicationId: string = '';
    other_display_name: string = '';
    constructor(public http: HttpClient) {}
    async ngOnInit() {
        // Your unique Azure Communication service endpoint 
        const ConnectionString = 'xxxxxxxx';
        const client = new CommunicationIdentityClient(ConnectionString);
        const user = await client.createUser();
        const token = await client.getToken(user, ["chat"]);
        this.userAccessToken = token.token;
        this.communicationUserId = user.communicationUserId;
        this.chatClient = new ChatClient(this.endpointUrl, new AzureCommunicationTokenCredential(this.userAccessToken));
    }
    async createChatThread() {
        let createChatThreadRequest = {
            topic: this.Name
        };
        let createChatThreadOptions = {
            participants: [{
                id: {
                    communicationUserId: this.communicationUserId
                },
                displayName: this.display_name
            }]
        };
        let createChatThreadResult = await this.chatClient.createChatThread(createChatThreadRequest, createChatThreadOptions);
        let threadId = createChatThreadResult.chatThread.id;
        console.log(`Thread created:${threadId}`);
        this.threadLink = 'http://localhost:4200/chat/' + threadId;
        this.chatThreadClient = this.chatClient.getChatThreadClient(threadId);
    }
    async AddUserParticipantToTheChatThread() {
        let addParticipantsRequest = {
            participants: [{
                id: {
                    communicationUserId: this.other_user_CommunicationId
                },
                displayName: this.other_display_name
            }]
        };
        let addUser = await this.chatThreadClient.addParticipants(addParticipantsRequest);
        console.log(addUser);
    }
    async listAllChatThreads() {
        let threads = this.chatClient.listChatThreads();
        for await (const thread of threads) {
            console.log(thread);
        }
    }
}

azure-chat. Component.html 

<label for="">Add Thread</label>
<br>
<br>
<input type="text" placeholder="Group Name" [(ngModel)]="Name" name="group Name">
<input type="text" placeholder="Your Display Name" [(ngModel)]="display_name" name="display name">
<button (click)="createChatThread()">Submit</button>
<br>
<br>
<a *ngIf="threadLink" href="{{threadLink}}">{{threadLink}}</a>
<br>
<br>
<br>
<br>
<br>
<div *ngIf="threadLink">
  <label for="">Add user to thread</label>
  <br>
  <br>
  <input type="text" placeholder="User id" [(ngModel)]="other_user_CommunicationId" name="otherCommunicationUserId">
  <input type="text" placeholder="Display Name" [(ngModel)]="other_display_name" name="otherDisplayName">
  <button (click)="AddUserParticipantToTheChatThread()">Submit</button>
</div> 

chat-thread.component.ts 

import {
    Component,
    OnInit,
    ChangeDetectorRef
} from '@angular/core';
import {
    ChatClient,
    ChatThreadClient
} from '@azure/communication-chat';
import {
    HttpClient
} from '@angular/common/http';
import {
    AzureCommunicationTokenCredential
} from '@azure/communication-common';
import {
    ActivatedRoute
} from '@angular/router';
import {
    CommunicationIdentityClient
} from '@azure/communication-identity';
@Component({
    selector: 'app-chat-thread',
    templateUrl: './chat-thread.component.html',
})
export class ChatThreadComponent implements OnInit {
    endpointUrl = 'https://xxxxx.communication.azure.com';
    communicationUserId: any;
    userAccessToken: string = '';
    chatClient: ChatClient | any = null;
    topicName: string = '';
    displayName: string = '';
    currentThreadId: any;
    chatThreadClient: ChatThreadClient | any = null;
    messages: message[] = [];
    sendMsg: message = {
        message: '',
        sender: ''
    };
    constructor(public http: HttpClient, private changeDetection: ChangeDetectorRef, private route: ActivatedRoute) {}
    async ngOnInit(): Promise < void > {
        const ConnectionString = 'xxxxxxxx';
        const client = new CommunicationIdentityClient(ConnectionString);
        this.currentThreadId = this.route.snapshot.paramMap.get('threadid');
        this.communicationUserId = this.route.snapshot.paramMap.get('userid');
        let data = await client.getToken(this.communicationUserId, ["chat"]);
        this.userAccessToken = data.token;
        this.chatClient = new ChatClient(this.endpointUrl, new AzureCommunicationTokenCredential(this.userAccessToken));
        this.chatThreadClient = this.chatClient.getChatThreadClient(this.currentThreadId);
        this.setupHandlers();
    }
    async setupHandlers() {
        this.getListMessages();
        await this.chatClient.startRealtimeNotifications();
        this.chatClient.on("chatMessageReceived", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("chatMessageEdited", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("chatMessageDeleted", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("typingIndicatorReceived", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("readReceiptReceived", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("chatThreadCreated", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("chatThreadDeleted", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("chatThreadPropertiesUpdated", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("participantsAdded", ((state: any) => {
            this.getListMessages();
        }).bind(this));
        this.chatClient.on("participantsRemoved", ((state: any) => {
            this.getListMessages();
        }).bind(this));
    }
    async getListMessages() {
        this.messages = [];
        const messages = this.chatThreadClient.listMessages();
        for await (const message of messages) {
            if (message.type == "text") {
                let msg: message = {
                    sender: message.senderDisplayName,
                    message: message.content.message
                };
                this.messages.push(msg);
            }
        }
        this.changeDetection.detectChanges();
    }
    async sendMessage() {
        let sendMessageRequest = {
            content: this.sendMsg.message
        };
        let sendMessageOptions = {
            senderDisplayName: this.sendMsg.sender,
            type: 'text'
        };
        const sendChatMessageResult = await this.chatThreadClient.sendMessage(sendMessageRequest, sendMessageOptions);
        const messageId = sendChatMessageResult.id;
        this.sendMsg = {
            message: '',
            sender: ''
        };
    }
    async ListUsersInChatThread() {
        const participants = this.chatThreadClient.listParticipants();
        for await (const participant of participants) {
            console.log(participant);
        }
    }
    async RemoveUserFromChatThread(userId: any) {
        await this.chatThreadClient.removeParticipant({
            communicationUserId: userId
        });
        await this.ListUsersInChatThread();
    }
}
interface message {
    sender: string,
        message: string
}

chat-thread.component.html 

<div *ngFor="let message of messages;" class="row">
  <label for="">{{message.sender}}</label> :       <label for="">{{message.message}}</label>
</div>
<br>
<br>
<br>
<br>
<div class="col-md-12">
  <label for="">Send New Message</label>
  <br>
  <br>
  <input type="text" placeholder="Sender" [(ngModel)]="sendMsg.sender" name="sender">
  <input type="text" placeholder="Message" [(ngModel)]="sendMsg.message" name="message">
  <button (click)="sendMessage()">Submit</button>
</div> 

app-routing.module.ts 

import {
    ChatThreadComponent
} from './chat-thread/chat-thread.component';
import {
    AzureChatComponent
} from './azure-chat/azure-chat.component';
import {
    NgModule
} from '@angular/core';
import {
    RouterModule,
    Routes
} from '@angular/router';
const routes: Routes = [{
    path: '',
    component: AzureChatComponent
}, {
    path: 'chat/:threadid/:userid',
    component: ChatThreadComponent
}];
@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule]
})
export class AppRoutingModule {}

App.module.ts 

import {
    NgModule
} from '@angular/core';
import {
    BrowserModule
} from '@angular/platform-browser';
import {
    AppRoutingModule
} from './app-routing.module';
import {
    AppComponent
} from './app.component';
import {
    HttpClientModule
} from '@angular/common/http';
import {
    FormsModule
} from '@angular/forms';
import {
    AzureChatComponent
} from './azure-chat/azure-chat.component';
import {
    ChatThreadComponent
} from './chat-thread/chat-thread.component';
@NgModule({
    declarations: [
        AppComponent,
        AzureChatComponent,
        ChatThreadComponent
    ],
    imports: [
        FormsModule,
        HttpClientModule,
        BrowserModule,
        AppRoutingModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule {}

Once copied all the codes please run the application follow the below steps for Create a chat thread, Create a thread with 2 users, send a message to the thread, and Receive messages from a thread. 

Here I have created a Test Group Chat name with Admin for display name. Once entered text please click to submit the button and the thread was created. 

Example -1 

Example -2

Learn about Azure Communication Service Chat Integrated Angular 13.

Next, add otherCommunicationUserId to with display name and add more users using addParticipants functions. For example, created user communicationUserId, I have marked like xxxxx with the user name. Once created the users we can able to create the chat link. Like the format is = (Thread + "/ " + CommunicationUserId).

Learn about Azure Communication Service Chat Integrated Angular 13.

Once open the chat link in the browser follow the images below to send and receive messages from one to another. 

Test user 1 sent the message 

Learn about Azure Communication Service Chat Integrated Angular 13.

Test user 2 received the message and sent the message. 

Learn about Azure Communication Service Chat Integrated Angular 13.

Admin Received both Test user 1 & Test user 2 and sent the message.

Learn about Azure Communication Service Chat Integrated Angular 13.

Finally, Azure Communication Service integrated successfully with the angular application. We are to send and receive messages with our own chat window. I hope this article is most helpful for us.