Most chat applications need a typing indicator and in this tutorial, you'll learn how code your own.

“Someone is typing” indicators are a handy communication tool. If you know someone is there on the other end writing, you might stick around a bit longer to see their response. The fact that typing indicators update in real-time makes users feel connected in such a way they will probably spend more time typing on your app.

It’s a little-known fact that typing indicators in the real-world are actually a little bit wonky:

In this example from The Journal, the indicator only disappears 60 seconds after you started the text.

While knowing that someone is typing can be helpful, sticking around to see what they typed when they weren’t even typing is the first place is just annoying. In this tutorial, we will be using CometChat Pro which ensures real-time updates are nearly instant. We’ll also be adding a slick animated typing indicator to give users something nice to look at.

Chat window with typing indicator

In this case, when Iron Man (a made up test user) is typing, other participants in the group can see that “Iron man is typing”. Of course, you could apply the same logic to a one-on-one conversation too.

I encourage you to follow along as you’re bound to learn something new but if you’d just like the source code, you can find the example Vue chat code here.

Getting started

In the past, I wrote about how to build a group chat with Vue and uploaded the complete code to GitHub. Rather than start from absolute scratch, in this short tutorial, I am going to extend the previous application.

I also wrote about building a one on one chat with Vue and, while I won’t mention it again in this tutorial, you could well apply the same logic to one-on-one conversations.

With that out of the way, step one is to clone the starter template I made based on the previous tutorial:

git clone https://github.com/cometchat-pro-tutorials/vue-typing-indicators.git

This project contains a couple of required dependencies that you will need to install, the image assets specifically for this project, and a stylesheet to give the app an appealing look. So, once the installation process is complete, navigate to the project directory and install all the dependencies:

// change directory
cd vue-typing-indicators

// install dependencies
npm install

The preceding command will install the CometChat JavaScript SDK for this project (@cometchat-pro/chat ) and other Vue specific packages.

What is CometChat

Having mentioned CometChat a couple of times in the sections above, you are probably wondering what it is. CometChat is a service built in form of robust SDK and API. It was designed as a developer tool to help save hours of development whenever you need to add a chat feature to your application. With CometChat, you can also easily access other power packed suite of chat features such as One-on-One chat, group chat, voice and video and so on. More information can be found here on our official website.

Create a free CometChat account

To have access to all the functionalities offered by CometChat through its JavaScript SDK, you will need to create a free CometChat Pro account. Fill in all the required information and you will have a trial account set up for you. Then, head to your CometChat dashboard, add a new app by selecting v1 from the dropdown and enter the desired name for your app. Proceed to click on the + sign and wait for a couple of seconds for your new app to be created.

Once this is done, you will be redirected back to the initial page where your new app will be listed. Click the Explore button and then go to the API Keys tab. Copy and save both your APP ID and the API Key with fullAccess scope that was automatically generated for your application, somewhere, as you will need it later.

You are now equipped with the appropriate credentials required to communicate with CometChat server through the use of the JavaScript SDK. We will utilize the credentials created here to run our chat application in the next section.

Run the group chat application

With the starter project downloaded from GitHub, let’s run the application and ensure that it is functioning as a group chat application at the moment. Before that, create a new file named .env within the root directory of the application and add the following code to it:

// .env
VUE_APP_COMMETCHAT_API_KEY=YOUR_API_KEY                
VUE_APP_COMMETCHAT_APP_ID=YOUR_APP_ID
VUE_APP_COMMETCHAT_GUID=YOUR_GROUP_GUID

This is an environment configuration file where we will define environment variables with the values of our CometChat account credentials. Ensure that you replace YOUR_API_KEY, YOUR_APP_ID, and YOUR_GROUP_GUID placeholder with the appropriate values as obtained from your CometChat dashboard.

Next, while you are still within the vue-typing-indicator project directory, run the following command to start the application:

npm run serve

Navigate to the http://localhost:8080 and enter any of the test users (i.e superhero1 , superhero2, superhero3 ) to start a chat:

You can now type a message to start a chat. Of course, the chat history will be empty at the moment:

Feel free to open another window and login with another user and then proceed to send messages to the group. If everything works properly, you now have a functioning group chat and in the next section, we will start implementing the typing indicator as mentioned earlier.

Add typing indicators

What we want to achieve here is pretty straight forward. Once a user starts typing, we want to grab the username of such an authenticated user and show an animated typing indicator to indicate that such a user is currently typing. For the typing animation, we will use the code from the awesome pen created by Jimmy Yoon.

Start typing
To check if a user has started typing we will use @keyup to listen for keyboard events within the input field and then notify CometChat by calling the method startTyping() within the TypingIndicator class from CometChat SDK. To begin, navigate to the src/views folder and open the Chat.vue file. Once you are done, scroll down to the <script></script> section and include the method named startTypingEvent() immediately after the sendGroupMessage() function:

// ./src/views/Chat.vue

<template>
...
</template>
<script>
  ...
  methods: {
    ...
    sendGroupMessage() {
    ...
    },
    // add startTypingEvent method
    startTypingEvent() {
      let receiverId = process.env.VUE_APP_COMMETCHAT_GUID;
      let receiverType = CometChat.RECEIVER_TYPE.GROUP;
      
      let typingNotification = new CometChat.TypingIndicator(
        receiverId,
        receiverType
      );
      CometChat.startTyping(typingNotification);      
    }    
  }
};
</script>

From the new method defined above, we passed the receiverId and the receiverType to the TypingIndicator class. This will ensure that the typing indicator’s notification is sent to the right receiver, which is a group with the specified GUID. This group will now be able to listen and receive the information via the MessageListener class. More about that later in the tutorial.

Next, locate the input field and add the @keyup=``"``startTypingEvent()``" to listen to the keyboard event on the input field and then call the startTypingEvent() method that was created earlier:

// ./src/views/Chat.vue

<template>
...
  <div class="msg-bottom">
    <form class="message-form" v-on:submit.prevent="sendGroupMessage">
      <div class="input-group">
                    <!-- Add typing event -->
        <input type="text" class="form-control message-input" @keyup="startTypingEvent()" placeholder="Type something" v-model="chatMessage" required>
          <spinner
            v-if="sendingMessage"
            class="sending-message-spinner"
            :size="30"
          />
      </div>
    </form>
  </div>  
...
</template>

Incoming typing indicator

Since we have been able to send typing indicator information in the previous section, the next thing is for the application to receive the detailed information once a user starts or ends typing. The information can be received within the onTypingStarted() and onTypingEnded() method of the MessageListener class.

To configure this, add a new data property named typingUsers[] within the data option as shown below. Also, immediately after the onTextMessageReceived()method within the message listener class, add two more methods named onTypingStarted() and onTypingEnded() and then update the contents as shown here:

// ./src/views/Chat.vue

<script>
...
export default {
  ...
  data() {
    return {
      ...
      // add typingUsers array
      typingUsers: []
    };
  },
  mounted() {
    ...
    CometChat.addMessageListener(
      listenerID,
      new CometChat.MessageListener({
        ...
        // add TypingStarted and TypingEnded
        onTypingStarted: typingIndicator => {
          console.log('Typing started :', typingIndicator);
          this.typingUsers.push(typingIndicator.sender);
        },
        onTypingEnded: typingIndicator => {
            console.log('Typing ended :', typingIndicator);
            this.typingUsers = this.typingUsers.filter(
              user => user.uid !== typingIndicator.sender.uid
            );
        }
      })
    );
  },
  ...
};
</script>

Here, within the onTypingStarted() method, we obtained the details of the user that is typing a message in form of an object and push it into the typingUsers[] property. Also, as soon as the user is done typing, we used the onTypingEnded() method to update the list of users within the typingUsers[] array by filtering the details of the currently authenticated user out of the array. This will ensure that the logged in user will not see his or her username while typing. Cool, right?

Show username and animated indicator

To show the username of the currently typing user update the <template></template> section of Chat.vue page with the following:

// ./src/views/Chat.vue
<template>
...
  <div class="chat-page">
    <div class="msg-inbox">   
      ...   
      <div>
          <div class="currently-typing-wrapper">
            <div>
              <p v-if="typingUsers.length === 1"> {{typingUsers[0].name}} is typing </p>
              <p v-else-if="typingUsers.length === 2"> {{typingUsers[0].name}} and  {{typingUsers[1].name}} are typing </p>
              <p v-else-if="typingUsers.length > 2"> Several people are typing</p>
            </div>
            <div class="container-dot" v-if="typingUsers.length > 0">
              <span class="dot"></span>
              <span class="dot"></span>
              <span class="dot"></span>
            </div>
          </div>
      </div>
      ... 
    </div>
  </div>
...
</template>

We conditionally rendered the username(s) of the users that are currently typing and also show the animated typing indicator. When more than two people are typing the application will show a message indicating that “Several people are typing”. If you missed any of the steps, check here for the complete Chat.vue file for this application.

Finally, update the stylesheet of this application in ./src/App.css by adding the following content:

// ./src/App.css

...
/* include typing indicator style */

.currently-typing-wrapper {
  background: #f8f9fb;
  padding: 12px;
  display: inline-flex;
  width: 100%;
  flex-direction: row;
  align-content: center;
  justify-items: center;
  height: 50px;
}
.container-dot {
  padding-left: 15px;
  display: inline-block;
}
.dot {
  height: 10px;
  width: 10px;
  border-radius: 100%;
  display: inline-block;
  background-color: #B4B5B9;
  animation: 1.2s typing-dot ease-in-out infinite;
}
.dot:nth-of-type(2) {
  animation-delay: 0.15s;
}
.dot:nth-of-type(3) {
  animation-delay: 0.25s;
}
@keyframes typing-dot {
  15% {
    transform: translateY(-35%);
    opacity: 0.5;
  }
  30% {
    transform: translateY(0%);
    opacity: 1;
  }
} 

Test the application

Restart the application if it is not currently running by using the npm run serve command. Then navigate to http://localhost:8080 to view it

Login
Open the application in two separate windows and login with any two of the test users:
superhero1, superhero2 or superhero3

Type a message to view the indicator
Once you can log in from both window, type a message and you will see the typing indicator showing the username of each user during the process:

Conclusion

In this tutorial, you have been able to extend the chat functionality of a Vuejs group chat application by including an animated typing indicator. This new feature that you just implemented here will go a long way to boost the interactivity of your chat application.

Feel free to check the complete source code here on the master branch of this repository and don’t forget to visit CometChat documentation for more features for your application and also check out other awesome comprehensive tutorials from our team.