Build Chat Application On MEA2N Stack - Part Two

In the previous part of the article series, Build Chat Application On MEA2N Stack – Part One, we built a basic chat application on Node.js platform using Express, Angular 2 and socket.io. In this article, we are going to use MongoDB Atlas for saving our chats and retrieving history whenever user will be requested for it.

Prerequisites

You can pull the code from GitHub.

Setup MongoDB Atlas

MongoDB Atlas is a cloud-hosted MongoDB service. MongoDB team will perform DB management, setup, and configuration, software patching, monitoring, backups and clustering.

To create MongoDB instance in the cloud, go to https://www.mongodb.com/cloud/atlas. Click on ‘Get Started for free’. Provide your information and get started. If you have already signed up, then login to the site.

Here you will see clusters created by you on the dashboard. To create a cluster, click on ‘Build a New Cluster’. It will pop up the details page. We need to provide Cluster name, MongoDB version, Cloud provider region, and Instance Size. For demo purposes, we are going to use free tier. 



Provide cluster name of your choice and select M0 instance size which is free. It includes 512 MB of storage. Scroll down and provide the admin username and password, which will be used to connect to MongoDB. Click on "Confirm and Deploy". It will start creating the cluster. It will take time up to 10 minutes for free tier.

After cluster creation, select a cluster and click on ‘Connect’. It will pop up a window where you can provide from which IP Address MongoDB will be accessible. For the demo, I have selected that MongoDB will be accessible from anywhere. Then, click on ‘Connect your Application’.

 
Copy the connection string from the next page, which we will use to connect to MongoDB Atlas from our application. We are ready with MongoDB Atlas setup. Now we will update our code for chat history feature.

 

Implementation – Server side (code updates)

Open ‘Chat-App’ project created in previous article. Open a terminal and install mongoose by executing ‘npm install mongoose --save’ command. Then create ‘chatManager.js’ in ‘Chat-App’ folder. Open it and start writing your code.
  1. const mongoose = require('mongoose');  
  2. mongoose.connect("mongodb://coder2xx:<password>@cluster4-shard-00-00-i2q0s.mongodb.net:27017,cluster4-shard-00-01-i2q0s.mongodb.net:27017,cluster4-shard-00-02-i2q0s.mongodb.net:27017/Akshay?ssl=true&replicaSet=Cluster4-shard-0&authSource=admin");  
  3.   
  4. const db = mongoose.connection;  
  5. db.on('error', () => {  
  6.     console.error('Connection error for MONGODB...');  
  7. });  
  8. db.once('open', () => {  
  9.     console.log("Connected to MONGODB successfully...");  
  10. });
Here, we are loading ‘mongoose’ module using require function. Then, connect function is called by passing a connection string parameter. We are using connection string which is copied from MongoDB Atlas setup. On error and open events for DB, we are logging respective messages to console. 
  1. const schema = mongoose.Schema;  
  2. const chatSchema = {  
  3.     from: String,  
  4.     clientId: String,  
  5.     text: String  
  6. };  
  7. const chatModel = mongoose.model('Chat'new schema(chatSchema));  
Here, schema for chat object is created using schema property of mongoose. Our chat history will include from address, client id and chat text.
  1. const save_chat = function (chat) {  
  2.     console.log(chat);  
  3.     var data = new chatModel({  
  4.         from: chat.from,  
  5.         clientId: chat.clientId,  
  6.         text: chat.text  
  7.     });  
  8.     data.save(function (err, fluffy) {  
  9.         if (err) {  
  10.             return console.error(err);  
  11.         }  
  12.     });  
  13. };  
  14.   
  15. const get_history = function (callback) {  
  16.     chatModel.find(function (err, chats) {  
  17.         if (err) return console.error(err);  
  18.         console.log(chats);  
  19.         return callback(chats);  
  20.     });  
  21. };  
  22.   
  23. module.exports = { saveChat: save_chat, getHistory: get_history };  
Then we need to add functions to save chat and retrieve chat history. In ‘save_chat()’ method, we will create new object of chatModel and call save method against it, which will save data to MongoDB. And in ‘get_history()’ method, we are calling find method against chatModel and returning a result with callback method.
 
Now open entry file of our application which is ‘starter.js’.
  1. const chatsManager = require("./chatsManager.js");  
 We need to load our chatsManager module to use its exported methods. 
  1. socket.on("send_message", (message) => {  
  2.         console.log(socket.client.id + ":)" + message);  
  3.         sockets.emit("new_message", { from: socket.client.id, text: message });  
  4.         chatsManager.saveChat({  
  5.             from: socket.client.id,  
  6.             clientId: socket.client.id,  
  7.             text: message  
  8.         });  
  9.     });  
  10.     socket.on("get_history", () => {  
  11.         console.log("Chat history request from " + socket.client.id);  
  12.         chatsManager.getHistory((chats) => {  
  13.             console.log("completed...");  
  14.             socket.emit("take_history", chats);  
  15.         });  
  16.     });  

Here we need to update ‘send_message’ event listener for save functionality. We have added call to chatsManager.saveChat() function. Then we have added ‘get_history’ event listener, which will get chat history by calling chatsManager.getHistory() method. It will emit ‘take_history’ event for requested client only. We are ready with server side updates. Now it's time to update client side.

Implementation – Client side (code updates)

Now open app.component.ts and update the code as mentioned.
  1. clearChatWindow = () => {  
  2.   this.messages = [];  
  3. };  
  4.   
  5. loadChatHistory = () => {  
  6.   this.socket.emit("get_history");  
  7. };  

clearChatWindow() and loadChatHistory() functiona are added to component. ‘clearChatWindow()’ will assign empty array to messages property. And loadChatHistory() will emit ‘get_history’ event.

  1. this.socket.on("take_history", (data) => {  
  2.   this.messages = data;  
  3. });  

Then, add an event listener for ‘take_history’ event. The response received from the event will be directly assigned to messages property. Response is an array of chats sent from the server.

Now, open app.component.html. And add two buttons, one for clearing chat history and another for requesting chat history. Call clearChatWindow() and loadChatHistory() functions on their clicks respectively.

  1. <button (click)="clearChatWindow()" class="btn btn-default" title="clear chat window"><i class="fa fa-trash" aria-hidden="true"></i></button>  
  2.   
  3. <button (click)="loadChatHistory()" class="btn btn-default" title="load chat history"><i class="fa fa-history" aria-hidden="true"></i></button>  

We are ready with our code. Let’s build an Angular application by executing ‘ng build’ command. Then run ‘node starter.js’ command to start our application.

Open two browsers and hit ‘http://localhost:9696’ from both the browsers. And start chatting…

In the following screen capture, Amit (user on left window), clears the chat by clicking on the "Delete" button, and reload the chat history from MongoDB by clicking on load chat history button.

 

You can check chat history is getting added in MongoDB using Compass. Use same connection string. 

 

This is basic chat application implementation on MEA2N stack. In future articles we will discuss about building APIs using NodeJs. 


Similar Articles