Skip to content

All topics  /  Node.js

How to Build Chat Application With Socket.io Using Node Js Express?

Node.js ·

For teams turning “How to Build Chat Application With Socket.io Using Node Js Express?” into a repeatable delivery task, the complete guide can document setup, troubleshooting and review time; managers should interpret those records alongside reliability and completed work, not as a stand-alone score.

Package and operating-system behaviour can change, so verify the commands and supported versions through the Node.js project before running them on a production host.

Hello Friends,

In this article, we will be using Socket.io and HarperDB to build a full-stack, real-time chat application with chat rooms.

This will be a great project to learn how to put together full-stack apps, and how to create an app where the backend can communicate with the frontend in real-time.

Step 1: Create Chat App Directory


In this step, open your terminal and execute the following command to create a chat app directory:

mkdir chat-app

Step 2: Install Node Express JS, Socket.io, and jQuery

In this step, you need to install node js express and jquery in your chat app. So, execute the following command:

cd chat-app
npm init -y
npm install
npm install express
npm install jquery
npm install socket.io

Step 3: Create Index.html and Style.css

In this step, you need to create index.html file and add the following code into it:

<!doctype html>
<html>
    <head>
        <title>How to Build Chat Application With Socket.io Using Node Js Express? - Nicesnippets.com</title>
        <link rel="stylesheet" href="style.css">
    </head>
    <body>
        <ul class="pages">
            <li class="chat page">
                <div class="chat_area">
                    <ul class="messages"></ul>
                </div>
                <input class="input_message" placeholder="Type here..."/>
            </li>
            <li class="login page">
                <div class="form">
                    <h3 class="title">What's your nickname?</h3>
                    <input class="username_input" type="text" maxlength="14" />
                </div>
            </li>
        </ul>
        <script src="//code.jquery.com/jquery-3.5.0.js"></script>
        <script src="/socket.io/socket.io.js"></script>
        <script src="/chat.js"></script>
    </body>
</html>

After that, create style.css file and add the following code into it:

* { margin: 0; padding: 0; box-sizing: border-box; }
body { font: 13px Helvetica, Arial; }

 
ul {
    list-style: none;
    word-wrap: break-word;
}
.log {
    color: gray;
}
.pages {
    height: 100%;
    /*margin: 0;
    padding: 0;*/
    width: 100%;
}
.page {
    height: 100%;
    position: absolute;
    width: 100%;
}
.login.page {
    background-color: #000;
}
.login.page .form {
    height: 100px;
    margin-top: -100px;
    position: absolute;
    text-align: center;
    top: 50%;
    width: 100%;
}
.login.page .form .username_input {
    background-color: transparent;
    border: none;
    border-bottom: 2px solid #fff;
    outline: none;
    padding-bottom: 15px;
    text-align: center;
    width: 400px;
}
.login.page .title {
    font-size: 200%;
}
.login.page .username_input {
    font-size: 200%;
    letter-spacing: 3px;
}
.login.page .title, .login.page .username_input {
    color: #fff;
    font-weight: 100;
}
.chat.page {
    display: none;
}
.input_message {
    font-size: 100%;
}
.chat_area {
    height: 100%;
    padding-bottom: 60px;
}
.messages {
    height: 100%;
    margin: 0;
    font-size: 150%;
    overflow-y: scroll;
    padding: 10px 20px 10px 20px;
}
.message.typing .message_body {
    color: gray;
}
.username {
    font-weight: 700;
    overflow: hidden;
    padding-right: 15px;
    text-align: right;
}
.input_message {
    border: 10px solid #000;
    bottom: 0;
    height: 60px;
    left: 0;
    outline: none;
    padding-left: 10px;
    position: absolute;
    right: 0;
    width: 100%;
}

Step 4: Create Chat.js

In this step, you need to create a chat.js file and add the following code to it:

$(function() {
    var win = $(window);
    var usernameInput = $('.username_input'); // Input for username
    var messages = $('.messages'); // Messages area
    var inputMessage = $('.input_message'); // Input message input box
    var loginPage = $('.login.page'); // The login page
    var chatPage = $('.chat.page'); // The chatroom page
    var username;
    var connected = false;
    var typing = false;
    var currentInput = usernameInput.focus();
    var socket = io();
    const setParticipantsMessage = (data) => {
        var message = '';
        if (data.numberOfUsers === 1) {
            message += "There is 1 participant";
        } else {
            message += "There are " + data.numberOfUsers + " participants";
        }
        log(message);
    }
    const log = (message, options) => {
        var el = $('<li>').addClass('log').text(message);
        addMessageElement(el, options);
    }
    const setUsername = () => {
        username = cleanInput(usernameInput.val().trim());
        if (username) {
            loginPage.fadeOut();
            chatPage.show();
            loginPage.off('click');
            currentInput = inputMessage.focus();
            socket.emit('user_added', username);
        }
    }
    const sendMessage = () => {
        var message = cleanInput(inputMessage.val());
        if (message && connected) {
            inputMessage.val('');
            addChatMessage({
                username: username,
                message: message
            });
            socket.emit('new_message', message);
        }
    }
    const addChatMessage = (data, options) => {
        var typingMessages = getTypingMessages(data);
        options = options || {};
        if (typingMessages.length !== 0) {
            options.fade = false;
            typingMessages.remove();
        }
        var usernameDiv = $('<span class="username"/>').text(data.username).css('font-weight', 'bold');
        var messageBodyDiv = $('<span class="messageBody">').text(data.message);
        var typingClass = data.typing ? 'typing' : '';
        var messageDiv = $('<li class="message"/>').data('username', data.username).addClass(typingClass).append(usernameDiv, messageBodyDiv);
        addMessageElement(messageDiv, options);
    }
    const addChatTyping = (data) => {
        data.typing = true;
        data.message = 'is typing';
        addChatMessage(data);
    }
    const removeChatTyping = (data) => {
        getTypingMessages(data).fadeOut(function () {
            $(this).remove();
        });
    }
    const addMessageElement = (el, options) => {
        var el = $(el);

        
        // Setup default options
        if (!options) {
            options = {};
        }
        if (typeof options.fade === 'undefined') {
            options.fade = true;
        }
        if (typeof options.prepend === 'undefined') {
            options.prepend = false;
        }
        // Apply options
        if (options.fade) {
            el.hide().fadeIn(150);
        }
        if (options.prepend) {
            messages.prepend(el);
        } else {
            messages.append(el);
        }
        messages[0].scrollTop = messages[0].scrollHeight;
    }
    const cleanInput = (input) => {
        return $('<div/>').text(input).html();
    }
    const updateTyping = () => {
        if (connected) {
            if (!typing) {
                typing = true;
                socket.emit('typing');
            }
        }
    }
    const getTypingMessages = (data) => {
        return $('.typing.message').filter(function (i) {
            return $(this).data('username') === data.username;
        });
    }
    win.keydown(event => {

        
        //console.log('event.which: ' + event.which);
        // Auto-focus the current input when a key is typed

        
        if (!(event.ctrlKey || event.metaKey || event.altKey)) {
            currentInput.focus();
        }

        
        // When the client hits ENTER on their keyboard
        if (event.which === 13) {
            if (username) {
                sendMessage();
                socket.emit('typing_stop');
                typing = false;
            } else {
            setUsername();
        }
    }
    inputMessage.on('input', () => {
        updateTyping();
    });
    loginPage.click(() => {
        currentInput.focus();
    });
    inputMessage.click(() => {
        inputMessage.focus();
    });
    socket.on('login', (data) => {
        connected = true;
        var message = "Welcome to Nodejs Chat Room";
        log(message, {
            prepend: true
        });
        setParticipantsMessage(data);
    });
    socket.on('new_message', (data) => {
        addChatMessage(data);
    });
    socket.on('user_joined', (data) => {
        log(data.username + ' joined');
        setParticipantsMessage(data);
    });
    socket.on('user_left', (data) => {
        log(data.username + ' left');
        setParticipantsMessage(data);
        removeChatTyping(data);
    });
    socket.on('typing', (data) => {
        addChatTyping(data);
    });
    socket.on('typing_stop', (data) => {
        removeChatTyping(data);
    });
    socket.on('disconnect', () => {
        log('You have been disconnected');
    });
    socket.on('reconnect', () => {
        log('You have been reconnected');
        if (username) {
            socket.emit('user_added', username);
        }
    });
    socket.on('reconnect_error', () => {
        log('Attempt to reconnect has failed');
    });
});

Note that The chat.js functions will work, as follows:

  • The function setParticipantsMessage() displays the total number of participants currently in the chat room.
  • log() function logs the message in the gray color text on the chat window.
  • setUsername() function displays the user name on the chat window once he/she enters the name on the initial screen where it asks for a nickname.
  • sendMessage() sends or broadcasts the message to the active participants.
  • addChatMessage() adds the message to the chat window. While someone is typing it shows the person is typing otherwise once typing is done it sends the message to the window.
  • addChatTyping() shows while someone is typing.
  • removeChatTyping() removes typing once someone has just finished typing and hit the enter key.
  • win. key down determines the events and accordingly it works with the events.
  • Step 5: Create index.js

    In this step, you need to open the index.js file and add the following code to it:

    var path = require('path');
    var express = require('express');
    var app = express();
    var server = require('http').Server(app);
    var io = require('socket.io')(server);
    var port = process.env.PORT || 4000;
    server.listen(port, function(){
        console.log('Listening on %d:' + port);
    });
    app.use(express.static(path.join(__dirname, 'static')));
    var numberOfUsers = 0;
    io.on('connection', (socket) => {
        var userJoined = false;
        socket.on('new_message', (msg) => {
            socket.broadcast.emit('new_message', {
                username: socket.username,
                message: msg
            });
        });
        socket.on('user_added', (username) => {
            if (userJoined) return;
            socket.username = username;
            userJoined = true;
            numberOfUsers++;
            socket.emit('login', {
                numberOfUsers: numberOfUsers
            });
            socket.broadcast.emit('user_joined', {
                username: socket.username,
                numberOfUsers: numberOfUsers
            });
        });
        socket.on('typing', () => {
            socket.broadcast.emit('typing', {
                username: socket.username
            });
        });
        socket.on('typing_stop', () => {
            socket.broadcast.emit('typing_stop', {
                username: socket.username
            });
        });
        socket.on('disconnect', () => {
            if (userJoined) {
                --numberOfUsers;
                socket.broadcast.emit('user_left', {
                    username: socket.username,
                    numberOfUsers: numberOfUsers
                });
            }
        });
    });

    Step 6: Run Development Server

    You can use the following command to run the development server:

    //run the below command
    npm start

    After running this command open your browser and hit

    http://127.0.0.1:3000/