Node.js Socket.io Make a Basic Chat Application (Native JS) 03

Node.js Socket.io Make a Basic Chat Application (Native JS) 03

Video Tutorial

Overview

After going through the basic things about socket.io and client/server connections it is time to move to a bit more practical workflow that will hopefully help you better understand the working with the library and other sockets based libraries for your next big projects.

We are basically going to create a very simple chat application where there is one client (YOU) and a server (server on your localhost) they can send an received messages, you can also use more than one client but for the seek of this tutorial we are just going to use one browser and a server console to see it in action.

Make sure to watch the previous tutorials in the series for better understand the workflow and how we are going to create the chat application.

The app we are going to create in this tutorial it’s going to be very basic therefore I have a full Udemy Course Series To learn to Create a Desktop Chat App from Scratch using Socket.io, React, RESTFUL APIs, Electron and much more of frameworks and libraries check it from Here.

App Structure

The Application is going to be running on the browser with a very minimal UI, the interface consists of two major parts: the Top messages Area where all the sent and received messages going to appear and the Btoom Input area is where the client can enter and send the message to the other connected clients.

We are going to use basic native javascript, HTML & CSS with no preprocessors or libraries, here is the HTML page structure with the CSS style of the chat page.

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!-->
<html class="no-js">
<!--<![endif]-->
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="./app.css">
</head>

<body>
    <!--[if lt IE 7]>
      <p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="#">upgrade your browser</a> to improve your experience.</p>
    <![endif]-->

    <div class="container">
        <div id="container" class="chat-container">
            Chat Messages
        </div>
        <div class="input-container">
            <div class="chat-input">
                <input id="chat-input" type="text" placeholder="Enter Message" />
                <button id="submitBtn" type="submit" class="btn btn-success">Send</button>
            </div>
        </div>
    </div>

    <script src="./app.js"></script>
</body>
</html>

And CSS

html,
body {
    box-sizing: border-box;
    width: 100%;
    height: 100%;
}

body {
    padding: 4px;
}

.container {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
}

.chat-container {
    flex: 1;
    display: flex;
    flex-direction: column;
}

.input-container {
    display: flex;
}

.chat-input {
    width: 100%;
    height: 30px;
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-content: center;
}

.input-container input {
    width: 100%;
    height: 100%;
    padding-left: 15px;
}

#submitBtn {
    height: 36px;
}

the UI isn’t that great but can do the job perfectly for us since all we need to from it is understand the socket.io more in-depth.

Also, I’m using webpack to bundle the app.js into a more readable browser-supported bundled code, take a look on the structure.

--dist/
app.js  ///< Bundled version
index.html 
app.css
--src ///< you should put more files on it 
app.js ///< main work file
webpack.config.js ///< the webpack config file

Send Message

As we saw in the previous tutorials sending a message is as simple as sending a piece of data to the server then the received gonna process and send it to the destination user or users, in this case, we will forward the message from the server to all the connected users.

Let’s start by first creating the connection handler also we need to create a custom namespace for chat area that the clients gonna join in and talk.

//As you know we will use express and http server modules for serving our socket.io server app
const express = require("express");
const app = express();
const port = 3000;
const http = require("http").createServer();

const io = require("socket.io")(http);

//Create and listen for new connection on the /chat namespace 
io.of("/chat").on("connection", (socket) => {
   //As you know when we expect a piece of data to arrive then we need to register a handler for it\
   socket.on("newMsg", (data) => {
      console.log(`New Message received from the user ${data.username}: ${data.msg}`);
      //Now it is the most important part which is forwarding the message to other clients
      socket.brodcast.emit("newMessage", data);
     /*We use the brodcast flag to make sure all the connected clients will receive the message but 
      the one who sent the first msg*/
   });
});

We simply create a namespace /chat and add a listener for a connection then we simply add a newMsg event handler for handling sent message from a particular client, also we expect the client to send a data object that holds the username and msg properties which basically represents the name of the user (probably registered on the Service but in this case we just gonna use a static username), alongside that there is the original text message.

Finally, we use the broadcast flag on the socket that has sent the original msg so we would ensure that all the connected users to the namespace would receive the emitted event with the data but the one who sent the actual message.

In this case, we need to remove the broadcast flag on the socket emit method cause we only have one client that will test both the send and receiving functionality, but the correct way to use it is by providing the broadcast flag.

Now on the client side, we need to grab the message from the input bar and send it to the server by emitting the newMsg event that the server is currently listening on.

/*Client Side*/
const io = require("socket.io-client");
//First, Connect
let chat = io.connect("http://localhost:3000/chat"); ///< connect to the namespace 

//Hard coded username
const username = "islempenywis";

//a function that will help use the get and send the message to the server with username
function sendMessage() {
   //Get input text 
   let input = document.getElementById("chat-input");
   let msg = input.value;
   //Clear the Input (After Submitting the Message) better UX
   chat.emit("newMsg", {username, msg});
   //Finally emit the newMsg event with an object holding the username and text msg
}
/*Also, we have a submit button right next the text input bar that we need to bind the click handler to send the message*/
const btn = document.getElementById("submitBtn");
btn.onclick = () => {
   sendMessage();
}

When emitting the event we use the new ES6 Object building feature that helps us to put only the key without specifically specifying the value if the key and value pairs have the same variable name, pretty coll Hah!

You can try now to put something silly like (“Hi there from the other side”) on the input field and submit it, take a look on the server console you should be able to see the message gets printed out to you alongside you hard-coded username.

Receive Message

Receiving a message on the client side is pretty much the same as sending it and also we need to connect to the socket.io server.

//Add & Show a message on the Messages Container on the DOM 
function addMessage(container, data) {
   //Element to append (Add)
   let elm = document.createElement("p"); ///< just a simple text wrapper 
   //Set Content of the element to show the username and the message text content 
   elm.textContent = `${data.username}: ${data.msg}`; 
   //Finally, Append it to the DOM
   container.appendChild(elm);
}
//Listen for received messages & Show them 
chat.on("newMessage", (data) => {
   //Log it
   console.log("New Message: ", data.username, data.msg);
   //Add it to DOM 
   let container = document.getElementById("container");
   addMessage(container, data);
});

Now after removing the broadcast flag on the server (just for testing temporarily) now you can test that your self by sending a message and waiting for it on the same client, while what you can actually do is pull of two independent browser instances and try to run two separate client and chat together, believe me you are going to find it fun and enjoyable to talk to your self for a bit.

And that’s it for the Basic Chat App.

What’s Next

As you have seen it is very simple to start and create a chat application especially with the ease provided by the socket.io library for manipulating sockets and connecting/disconnecting for a remote/local server.

Well, what you can do now is go for the Udemy Course Series to create a real-world Full application from scratch using Socket.io and more interesting technologies, check it out from **Here.**