Build an Ionic chat app with TalkJS
TalkJS provides an API that you can use to add chat to your web and mobile apps. It includes features like a pre-built UI and out-of-the-box notifications. This tutorial will teach you how to create an Ionic chat app by integrating TalkJS.
We assume that you already have a basic understanding of Ionic. To follow this tutorial, you'll need an Ionic application to add TalkJS to – if you don't already have one, you can use Ionic's starter template.
In this tutorial we'll create an Ionic service that stores some hard-coded user data (in a real app you'll retrieve this from your database) and then set up conversations between these users with TalkJS. Let's get started.
Getting ready
First, you'll need to create a TalkJS account and get the App ID. You can find the App ID in the Settings tab of your TalkJS dashboard. We’ll start from a blank starter template and use Angular as our web framework on top of Ionic.
To install TalkJS with npm, run the following command in the root folder of your project:
npm install talkjs --save
Let's add our App ID to our environment variables inside environment.prod.ts
and environment.ts
:
TALKJS_APP_ID: 'YOUR_APP_ID'
Setting up the UI
Next we need to create an Ionic page for our chat. Run the following command:
ionic g page chat
The Ionic CLI will create a new folder and scaffold the skeleton code for our chat page. We will also generate a service for communicating with the TalkJS API:
ionic g service shared/services/chat
This command will scaffold a service inside the shared/services
folder. Let's import the ChatService
class and inject it into the constructor in chat.page.ts
:
import { ChatService } from '../shared/services/chat.service';
constructor(private chatService: ChatService) { }
We will add some hardcoded data to the chat.page.ts
to use it for this chat example. You will probably pull this data from the database in a real app.
users = [
{
id: 0,
name: 'Ken',
email: 'ken@test-email.io',
photoUrl: 'https://i.picsum.photos/id/818/200/200.jpg?hmac=gfhJZngz3JDsSmE1obNFY5OeAQBVsJLED2VkwuGsC-o',
welcomeMessage: 'Welcome to the chat!',
role: 'default'
},
{
id: 1,
name: 'Denis',
email: 'denis@test-email.io',
photoUrl: 'https://i.picsum.photos/id/730/200/200.jpg?hmac=wK_2ZX79XZRP1wVJ-dW_r-OkOjiz1kK8eHIyTw2Lr6s',
welcomeMessage: 'Hi',
role: 'default'
},
{
id: 2,
name: 'Tim',
email: 'tim@test-email.io',
photoUrl: 'https://i.picsum.photos/id/521/200/200.jpg?hmac=J25eIJlH4Vz83r581TpDZbrmu21tzbZMognm7gqkoWo',
welcomeMessage: 'Hello friend',
role: 'default'
},
{
id: 3,
name: 'Sarah',
email: 'sarah@test-email.io',
photoUrl: 'https://i.picsum.photos/id/194/200/200.jpg?hmac=f1VYjvgDG_6vPwJyTb-Xl1HpXKM23stmhFUnmPE_yL8',
welcomeMessage: 'How can I help you?',
role: 'default'
},
{
id: 4,
name: 'Adam',
email: 'adam@test-email.io',
photoUrl: 'https://i.picsum.photos/id/653/200/200.jpg?hmac=tZtho3csFdJ2rLHTTlT7WhXtDwbXgJNIIUvOQQb2dIo',
welcomeMessage: 'What\'s up?',
role: 'default'
}
];
To display the users
data on the frontend we will add the following code to our chat.page.html
template file:
<ion-header>
<ion-toolbar>
<ion-title>Chat</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<h3 class="page-title">Pick your chat partner</h3>
<ion-list>
<ion-item *ngFor="let user of users" type="button" (click)="chatInit(user)">
<ion-avatar slot="start">
<img [src]="user.photoUrl">
</ion-avatar>
<ion-label>
<h3>{{ user.name }}</h3>
<p>{{ user.email }}</p>
</ion-label>
<ion-icon name="chevron-forward"></ion-icon>
</ion-item>
</ion-list>
<div #inboxContainer id="inboxContainer">
</div>
<button ion-button #closeInboxBtn color="light" id="closeInboxBtn" (click)="closeInbox()">
<ion-icon name="chevron-back"></ion-icon> Close this chat
</button>
</ion-content>
This will create a list of users we can chat with. By clicking on a user in the list we are passing the information of that user to chatInit
function in order to initiate a chat session. Once the chat partner is selected, we'll display the inboxContainer
and closeInboxBtn
elements and mount
the TalkJS chat UI to the inboxContainer
.
Let's add a little bit of styling to it by adding the following code to our chat.page.scss
:
.page-title {
margin: 20px 0;
text-align: center;
}
#inboxContainer {
height: 90vh;
position: fixed;
top: 0;
width: 100%;
z-index: 999;
display: none;
}
#closeInboxBtn {
display: none;
position: fixed;
bottom: 0px;
height: 10vh;
width: 100%;
font-size: 18px;
line-height: 2;
background-color: #ff0000;
font-weight: 600;
ion-icon {
position: relative;
top: 6px;
font-size: 25px;
}
}
We need to define an element we'll use to display the inbox and a close button to hide the inbox. We will use the ViewChild
decorator.
@ViewChild('inboxContainer') inboxContainer!: ElementRef;
@ViewChild('closeInboxBtn') closeInboxBtn!: ElementRef;
Now let's go to the chat.service.ts
file to write the code that will interact with the TalkJS API. We need to import the app ID from the environment file and Talk
from TalkJS.
import Talk from 'talkjs';
import { environment } from 'src/environments/environment';
We’ll use the currentUser
object to store the data of the user that is currently logged in to this instance of TalkJS.
currentUser: Talk.User;
Now let's start the session by using Talk.Session
. A session represents a connection between the mobile app and TalkJS. A session begins after authentication through the app ID and ends when the app is closed. Let's add a function to initiate a TalkJS session:
async startSession() {
return Talk.ready.then(() => {
this.currentUser = new Talk.User({
id: 99,
name: 'Omar',
email: 'omar@test-email.io',
photoUrl: 'https://i.picsum.photos/id/681/200/200.jpg?hmac=GBX3TnpfRpzN-ZDEpA01hkf2-G7DkpMs53xqLpv8pa4',
welcomeMessage: 'Hey there!',
role: 'default'
});
const session = new Talk.Session({
appId: environment.TALKJS_APP_ID,
me: this.currentUser
});
return session;
});
}
First, we need to assign the value to the currentUser
object and create the session
object. As before we're using hard-coded user data here, which would normally be retrieved from a database.
Starting a conversation
Next, we'll start a conversation between our current user and the other user we select from the user list:
async startConversation(session: Talk.Session, user: any) {
const otherUser = new Talk.User({
id: user.id,
name: user.name,
email: user.email,
photoUrl: user.photoUrl,
welcomeMessage: user.welcomeMessage,
role: user.role
});
const conversation = session.getOrCreateConversation(Talk.oneOnOneId(this.currentUser, otherUser));
conversation.setParticipant(this.currentUser);
conversation.setParticipant(otherUser);
return conversation;
}
We use the getOrCreateConversation
method can be used to begin a conversation and the setParticipant
method to add our users to it. The oneOnOneId
method uses the users IDs to create a unique ID for the conversation
.
Creating the inbox element
We'll call the startConversation
method and display TalkJS's Inbox UI when we click on a user in the list:
async createInbox(session: Talk.Session, user: any) {
const conversation = await this.startConversation(session, user);
const inbox = session.createInbox();
inbox.select(conversation);
return inbox;
}
We're passing a session object and a user object to this function so we can initiate a conversation. The conversation is created by assigning the return value of the startConversation
function to the conversation
constant. We are using the createInbox
function to display the chat UI.
Removing the inbox element
We'll also want a removeInbox
method to destroy the inbox when we click on the close button:
removeInbox(inbox: Talk.Inbox) {
inbox.destroy();
}
We can pass the inbox instance to our removeInbox
method and remove it by using the destroy
function provided by TalkJS.
Wrapping it up
Now all we need to do is to import an instance of TalkJS into chat.page.ts
and write the logic for invoking the functions that are defined in chat.service.ts
.
import Talk from 'talkjs';
We need to define a variable that will contain the data that is returned by ChatServices createInbox
function.
inbox: Talk.Inbox;
When the user clicks on a list item the chatInit
function is called.
async chatInit(user: any) {
const session = await this.chatService.startSession();
this.inbox = await this.chatService.createInbox(session, user);
this.inbox.mount(this.inboxContainer.nativeElement);
this.showChat();
}
After starting a session and creating an inbox we need to display the chat on the screen by using the showChat
function:
showChat() {
this.inboxContainer.nativeElement.setAttribute('style', 'display: block');
this.closeInboxBtn.nativeElement.setAttribute('style', 'display: block');
}
The user can click on the close button to close the chat by calling the closeChat
function:
closeChat() {
this.chatService.removeInbox(this.inbox);
this.closeInboxBtn.nativeElement.setAttribute('style', 'display: none');
this.inboxContainer.nativeElement.setAttribute('style', 'display: none');
}
Conclusion
To recap, in this tutorial we have:
- created an Ionic service that provides user data
- created an Ionic template that displays a list of users
- integrated TalkJS into the service so that you can start a conversation when you click on a user in the list
For more ideas for how to use TalkJS in your app, see our docs.