Real Time chatting app using Nodejs, Mysql, AngularJs and Socket.io – Part 1

We all have seen the tutorials and article on how to create Chat Room in Node.js where multiple users can send and receive messages of each other. But in this article, I will explain how we can create Private Real Time chatting app.

In this application, we will have,

  1. A user chat list, which will show the recent chats as well as online users.
  2. We will show the typing indicator.
  3. We will have notification system when a user receives a new message.
  4. And most importantly we will send a message to the unique user to make it private chat.

As this article seems lengthy, I have divided it into 3 parts. Each part of  this article covers unique part in building the Private Real Time chatting app.

Part 1:  Covers the Overview, Setting up the server and entire Login page & Registration page operation.

Part 2:  Covers the Homepage workflow and it's CRUD operations.

Part 3:  Building Simple Realtime Chat Application.

Looking for Real Time private chatting app using Angular 2, we have that too.

But before going any further, let's take  a look at the final outcome of this article.

homepage realtime private real-time chatting app

1. Homepage (Private chatting application)

 

chat list with typing notification private real-time chatting app

 

2. Typing indicator (private chatting application)

 

popup notification private real-time chatting app

 

3. Notification when a user receives a new message

1. Overview :

Below you can see the folder structure for this application. In the middleware folder, we have our  config files, helper file which contains all the method  and files to handle routes. 

+--- middleware
|    \+-- auth-routes.js
|      +-- config.js
|      +-- db.js
|	  +-- helper.js
|     +---routes
|
+--- node_modules
|    \ body-parser
| 	 \ cookie-parser
| 	 \ ejs
| 	 \ express
|    \ express-session
|	 \ mysql
|    \ multer
|    \ socket.io
|
+--- views
|	\ angularjs-toaster
|	\ css
|		|
|		+-- bootstrap.min.css	
|		+-- style.css	
|	\ js
|		|
|		+-- jquery.min.js 
|		+-- bootstrap.min.js
|		+-- angular.min.js	
|		+-- angular-animate.min.js
|		+-- home_script.js (Script for Home Page)
|		+-- script.js (Script for Login & Registration Page)
|	\ img
|	\ uploads
|	+-- home.html
|	+--login.html
+---server.js
+---package.json

Prerequisites:

  1. Connecting nodejs app to Mysql.
  2. Sending message to specific user with socket.io.
  3. Typing notification in chatting application using nodejs and socket.io
  4. Showing notification using toaster in AngularJs

Once go through above articles if you are not familiar with those topics listed above and I assume reader of this article has the intermediate knowledge of Nodejs and  AngularJs. Here is our package.json file,

package.json 

{
  "name": "Real-Time-Private-Chatting-Codershood",
  "version": "0.0.1",
  "description": "Real-Time-Private-Chatting-Codershood",
  "author": "Shashank Tiwari",
  "license": "MIT",
  "dependencies": {
    "express": "^4.13.4",
    "express-session": "^1.13.0",  
    "cookie-parser": "^1.4.1",
    "body-parser": "^1.15.0",
    "mysql": "^2.10.2",
    "socket.io": "^1.4.5",       
    "ejs": "^2.4.1",  
    "multer": "^1.1.0"
  }
}

Okay, let's starts by creating MySql Database.

 

2. Creating MySQL Database

Overall we are going to create 3 tables.

  1. User: This table holds the information about users.
  2. Conversation: This table holds the conversation Id between users.
  3. Conversation_reply: This table holds the messages associated with Conversation Id.

real time chatting app using nodejs,mysql,angularJs and socket.io database tables

To create these tables, Open the PHPMyAdmin which is located at http://localhost/phpmyadmin and execute these SQL queries, you can use PHPMyAdmin graphical interface to create tables if you are familiar with it.

SQL QUERIES:

CREATE DATABASE chat;

USE chat;

CREATE TABLE IF NOT EXISTS `user` (
  `id` int(22) NOT NULL AUTO_INCREMENT,
  `name` varchar(200) NOT NULL,
  `password` varchar(200) NOT NULL,
  `p_photo` varchar(200) NOT NULL,
  `timestamp` int(255) NOT NULL,
  `online` varchar(2) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `conversation` (
  `id` int(22) NOT NULL AUTO_INCREMENT,
  `from_id` varchar(200) NOT NULL,
  `to_id` varchar(200) NOT NULL,
  `timestamp` varchar(200) NOT NULL,
  `con_id` int(255) NOT NULL,
  PRIMARY KEY (`id`)
);

CREATE TABLE IF NOT EXISTS `conversation_reply` (
  `id` int(255) NOT NULL AUTO_INCREMENT,
  `reply` text NOT NULL,
  `from_id` int(11) NOT NULL,
  `to_id` int(11) NOT NULL,
  `timestamp` varchar(500) NOT NULL,
  `con_id` int(255) NOT NULL,
  PRIMARY KEY (`id`)
);

3. Creating Server Files for  Real Time chatting app:

1. Create a folder named as middleware inside root directory this folder contains files which take care our routes, configuration and Database connection.

2. Create a file named as config.js inside middleware folder. This file will take of express related configuration.

config.js:

var express = require("express");
var path= require('path'); 
 
var method=config.prototype;

function config(app){
    
    // Setting .html as the default template extension
	app.set('view engine', 'html');

	// Initializing the ejs template engine
	app.engine('html', require('ejs').renderFile);

	// Telling express where it can find the templates
	app.set('views', (__dirname + '/../views'));

	//Files 
	app.use(express.static(path.join('views')));
	
}

method.get_config=function(){
	return this;
}

module.exports = config;

3. Create a file db.js inside middleware folder. This file takes care of database connection.

db.js:

/*requiring mysql node modules */
var mysql = require("mysql");

var method = db.prototype;

function db() {
    /*
    	creating MySql database connection 
	*/
	var con = mysql.createPool({
		host : 'localhost',
	  	user : 'root',
	  	password : '',
	  	database : 'chat'
	});
	this.connection=con;
}
method.getcon = function() {
	return this;
};

module.exports = db;

4.  Now create a file called  server.js. which needs no introduction I believe codershood.info favicon.

server.js:

/*requiring node modules starts */

var app = require("express")();
var http = require('http').Server(app);
var io = require("socket.io")(http);
var Session = require('express-session');
var cookieParser = require('cookie-parser'); 
/*requiring node modules ends */


// the session is stored in a cookie, so we use this to parse it
app.use(cookieParser());

var Session= Session({
    secret:'secrettokenhere',
    saveUninitialized: true,
	resave: true
});


io.use(function(socket, next) {
	    Session(socket.request, socket.request.res, next);
});


app.use(Session);

var sessionInfo;

/* requiring config file starts*/
var config =require('./middleware/config.js')(app);
/* requiring config file ends*/

/* requiring config db.js file starts*/
var db = require("./middleware/db.js");
var connection_object= new db();
var connection=connection_object.connection; // getting conncetion object here 
/* requiring config db.js file ends*/


/* 
	1. Requiring auth-routes.js file, which takes care of all Login & Registration page operation.
	2. Passing object of express, Database connection, expressSession and cookieParser.
	3. auth-routes.js contains the methods and routes for Login and registration page. 
*/
require('./middleware/auth-routes.js')(app,connection,Session,cookieParser,sessionInfo);
/* 
	1. Requiring routes.js file, which takes handles the Home page operation.
	2. Passing object of express, Database connection and object of socket.io as 'io'.
	3. routes.js contains the methods and routes for Home page  
*/
require('./middleware/routes.js')(app,connection,io,Session,cookieParser,sessionInfo);

/*
	Running our application  
*/
http.listen(81,function(){
    console.log("Listening on http://127.0.0.1:81");
});

5.  Create file a named as auth-routes.js file, which contains routes to handle all the login and registration page.

auth-routes.js:

/*requiring node modules starts */

var bodyParser = require('body-parser');
var multer  = require('multer');
var fs = require('fs');
/*requiring node modules starts */

/*Telling Multer where to upload files*/
var upload = multer({ dest: './views/uploads' });


var method=routes.prototype;

function routes(app,connection,sessionInfo){
    
    var file_path="";
	app.use(bodyParser.urlencoded({
		extended: true
	}));
	app.use(bodyParser.json());

	
	app.get('/', function(req, res){

		sessionInfo=req.session;
		/*Render Login page If session is not set*/
		if(sessionInfo.uid){
			res.redirect('/home#?id='+sessionInfo.uid);
		}else{
			res.render("login");		
		}
	});

	/*
		post to handle Login request
	*/
	app.post('/login', function(req, res){


		sessionInfo=req.session;

		username=req.body.username;
		password=req.body.password;

		var data={
			query:"select * from user where password='"+password+"' and name='"+username+"' ",
			connection:connection
		}
		/*
			Calling query_runner to run  SQL Query
		*/
		query_runner(data,function(result){
			var uid="";			
			result.forEach(function(element, index, array){
				uid=element.id;
			});

			if(result.length>0) {

				//setting session
				sessionInfo.uid = uid;

				var set_online={
					query:"update user set online='Y' where id='"+uid+"'",
					connection:connection
				}
				query_runner(set_online,function(result_online){});	
				result_send={
			    		is_logged:true,
			    		id:uid,
			    		msg:"OK"
			    };	    	
		    } else {
		    	result_send={
		    		is_logged:false,
		    		id:null,
		    		msg:"BAD"
		    	};
		    }
		    /*
				Sending response to client
			*/
		    res.write(JSON.stringify(result_send));
			res.end();
		});
	});

	/*
		post to handle username availability request
	*/
	app.post('/check_name', function(req, res){
		username=req.body.username;		
		var data={
			query:"select * from user where name='"+username+"'",
			connection:connection
		}
		query_runner(data,function(result){
			
			if(result.length>0) {
		    	result_send={
		    		msg:true
		    	};
		    } else {
		    	result_send={
		    		msg:false
		    	};
		    } 
		    res.write(JSON.stringify(result_send));
			res.end();
		});
	});

	/*
		post to Register username request
	*/
	app.post('/register', upload.single('file'), function(req, res, next){

		sessionInfo=req.session;
		/*
			Multer file upload starts
		*/
		var file_path = './views/uploads/' + Date.now()+req.file.originalname;
		var file_name = '/uploads/' + Date.now()+req.file.originalname;
		var temp_path = req.file.path;

		var src = fs.createReadStream(temp_path);
		var dest = fs.createWriteStream(file_path);		
		src.pipe(dest);
		/*
			Multer file upload ends
		*/
		src.on('end', function() {
			/*
				When uploading of file completes, Insert the user.
			*/
			var insert_data = {
				id:'',
				name:req.body.username,
				password:req.body.password,
				p_photo:file_name,
				timestamp:Math.floor(new Date() / 1000),
				online:'Y'
			};
			var data={
				query:"INSERT INTO user SET ?",
				connection:connection,
				insert_data:insert_data
			};		
			query_runner(data,function(result){
				
				//storing session ID
				sessionInfo.uid = result.insertId;

				if(result) {
					result_send={
			    		is_logged:true,
			    		id:result.insertId,
			    		msg:"OK"
			    	};
				}else{
					result_send={
			    		is_logged:false,
			    		id:null,
			    		msg:"BAD"
			    	};
				}
				res.write(JSON.stringify(result_send));
				res.end();		
			});
		});
		src.on('error', function(err) { 
			/*
				Sending Error 
			*/
			res.write(JSON.stringify("Error"));
			res.end(); 
		});
	});

	/*
		post to handle Logout request
	*/
	

}

method.getroutes=function(){
	return this;
}

module.exports = routes;

/*
	Making query_runner function to Run mysl queries
*/
var query_runner=function(data,callback){
	var db_conncetion=data.connection;
	var query=data.query;
	var insert_data=data.insert_data;
	db_conncetion.getConnection(function(err,con){
		if(err){
		  con.release();
		}else{
			db_conncetion.query(String(query),insert_data,function(err,rows){
		    con.release();
		    if(!err) {
		    	callback(rows);
		    } else {
		      console.log(err);  
		      console.log("Query failed");  
		    }        
		  });
		}
	});
}

3. Creating a Login and registration page

In this application, we are keeping track of every user and we are saving records and messages into our database tables. So let's give the interface to the user to log in and register.

1. Create login.html file in views folder and write below code.
login.html:

<html ng-app="login-register">
  <head>
      <title>Real Time Private Chatting : Codershood</title>
    <link rel="stylesheet" href="css/bootstrap.min.css">
	<link rel="stylesheet" href="css/style.css"> 
  </head>
  <body ng-controller="login-register">

    <!-- Main Div Wrapper starts-->
  	<div class="container index">
		
		
  		<!-- 
  			Login Box starts 
  		-->
		<div ng-hide="LoginBox" class="login box-container">
			
			<div class="heading">
		  		<h2 class="login-heading">Login</h2>        
			</div>

			<!-- User name Text Field -->
			<div class="input-group username-group">
		  		<span class="input-group-addon iconbg">
					<i class="glyphicon glyphicon-user"></i>
		  		</span>
		  		<input id="login-username" type="text" ng-model="username" class="form-control inputbg" name="username" value="" placeholder="username or email">
			</div>

			<!-- Password Text Field -->
			<div class="input-group password-group">
		  		<span class="input-group-addon iconbg">
					<i class="glyphicon glyphicon-lock"></i>
		  		</span>
		  		<input id="login-password" type="password" ng-model="password" class="form-control inputbg" name="password" placeholder="password">
			</div>

			<!-- ALert Box For Wrong Usernme and password combination -->
			<div class="alert-group" ng-hide="LoginAlert">
		  		<div class="alert alert-danger">
					Wrong Username and Password combination 
		  		</div>
			</div>
	
			<!-- Button to Login -->
			<div class="input-group">
				<button ng-click="login()"id="btn-login" class="btn btn-login btnbg">
					Login 
				</button>
			</div>

			<!-- Link for SingUp Box -->
			<div class="signup-box">
			  	<h4>Don't have an account ? <u><span ng-click="toggle_register()">SignUp</span></u></h4>
			</div>
		</div>
		<!-- 
  			Login Box ends 
  		-->

		
		<!-- 
  			Registration Box starts 
  		-->
		<div ng-hide="RegisterBox" class="register box-container">

			<div class="heading">
				<h2 class="login-heading">Register</h2>        
			</div>

			<!-- User name Text Field -->
			<div class="input-group username-group">
				<span class="input-group-addon iconbg">
					<i class="glyphicon glyphicon-user"></i>
			  	</span>
			  	<input id="register-username" type="text" ng-model="username"  class="form-control inputbg" name="username" value="" placeholder="username or email" ng-keyup="keyup_uncheck()" ng-keydown="keydown_uncheck()" ng-blur="blur_uncheck()"  ng-change="change_uncheck()">
			</div>

			<!-- ALert Box When username is already taken -->
			<div class="alert-group" ng-hide="RegisterAlert">
			  	<div class="alert alert-danger">
					This username is already taken. 
			  	</div>
			</div>

			<!-- Password Text Field -->			
			<div class="input-group password-group">
			  	<span class="input-group-addon iconbg">
					<i class="glyphicon glyphicon-lock"></i>
			  	</span>
			  	<input id="register-password" type="password" ng-model="password"  class="form-control inputbg" name="password" placeholder="password">
			</div>

			<!-- Field upload Image-->			
			<div class="input-group p_photo-group">
				<input id="p_photo-password" type="file" class="p_photo inputbg" file-model = "myFile" name="p_photo">
			</div>
			<div id="selectedFile" class="selectedFile" >Upload Profile Image:</div>

			<!-- Button to Register -->
			<div class="input-group">
				<button id="btn-login" class="btn btn-login btnbg" ng-click="register()">
					Register
			  	</button>
			</div>

			<!-- Link for Login -->
			<div class="signup-box">
				<h4>Already have an account ? <u><span ng-click="toggle_login()">SignIn</span></u></h4>
			</div>
		</div>
	</div>
	
  <script src = "js/angular.min.js"></script>
  <script src = "js/script.js"></script>
  <script src = "js/jquery.min.js"></script>
  <script src = "js/bootstrap.min.js"></script>
  </body>
</html>

2. Create javascript file named script.js  which contains code to perform  all action required for Login and registration page.

script.js:

var app = angular.module('login-register',[]);

/*creating Directive to Upload file starts*/
app.directive('fileModel', ['$parse', function ($parse) {
    return {
       restrict: 'A',
       link: function(scope, element, attrs) {
          var model = $parse(attrs.fileModel);
          var modelSetter = model.assign;
          
          element.bind('change', function(event){
             scope.$apply(function(){
                var files = event.target.files;
                /* 
                    Writing the selected file name below the Upload image
                */  
                angular.element( document.querySelector( '#selectedFile' )).html(files[0].name);
                modelSetter(scope, element[0].files[0]);
             });
          });
       }
    };
}]);
/*creating Directive to Upload file ends*/

app.controller('login-register', function ($scope,$http,$timeout,$window) {    
    
    /* variables for  Hide show starts*/
    $scope.LoginBox=false; 
    $scope.LoginAlert=true;
    $scope.RegisterAlert=true;
    $scope.RegisterBox=true;
    /* variables for  Hide show ends*/

    /* usernamme check variables starts*/
    var TypeTimer;                
    var TypingInterval = 1000;
    /* usernamme check variables ends*/
    

    /* Hide show Login and Registration box  starts */
    $scope.toggle_register = function() {
        $scope.RegisterBox = !$scope.RegisterBox;
        $scope.LoginBox = !$scope.LoginBox;
    };
    $scope.toggle_login = function() {
        $scope.LoginBox = !$scope.LoginBox;
        $scope.RegisterBox = !$scope.RegisterBox;
    };
    /* Hide show Login and Registration box ends*/
    

    /* Login operation starts*/
    $scope.login = function(){
        var data={
            username:$scope.username,
            password:$scope.password
        }

        $http.post('/login',data).success(function(data, status, headers, config) {
            if(data.is_logged){
                $scope.LoginAlert = true;
                $window.location.href = "/home#?id="+data.id;
            }else{
                $scope.LoginAlert = false;
            }
        }).error(function(data, status) {
            alert("Connection Error");
        });
    };
    /* Login operation ends*/

    

    /* usernamme check operation starts*/
    $scope.keyup_uncheck = function() {
        $timeout.cancel(TypeTimer);
        TypeTimer=$timeout( function(){
            var data={
                username:$scope.username
            }
            etc_function.check_username(data);            
        }, TypingInterval);
    };
    $scope.keydown_uncheck = function(){
        $timeout.cancel(TypeTimer);
    };
   
    $scope.blur_uncheck = function(){
        var data={
            username:$scope.username
        }
        etc_function.check_username(data);
        $timeout.cancel(TypeTimer); 
    };
    /* usernamme check operation ends*/


    /* Regsiter operation starts*/
    $scope.register = function(){
        var file_ext=["image/png","image/jpg","image/jpeg","image/gif"];
        var file_type_ok=true;
        var file = $scope.myFile;
        var file_size=Math.round(file.size/1024);

        file_ext.forEach(function(element, index){
            if(element===(file.type).toLowerCase()){
                file_type_ok=false;
            }
        });
        
        if(file_size>500){
            alert("Upload file below 500 KB.");
        }else if(file_type_ok){
            alert("Upload image file.");
        }
        else{
            var fd = new FormData();
            fd.append('file', file);
            fd.append('username',$scope.username);
            fd.append('password',$scope.password);
            $http.post("/register", fd, {
                transformRequest: angular.identity,
                headers: {'Content-Type': undefined}
            })
            .success(function(data, status, headers, config) {
                if(data.is_logged){
                    $scope.LoginAlert = true;
                    $window.location.href = "/home#?id="+data.id;
                }else{
                    $scope.LoginAlert = false;
                }
            })
            .error(function(){
                alert("Connection Error");
            });
        }
    };
    /* Regsiter operation ends*/

   
    /* Making Extra function*/
    var etc_function={
        check_username:function(data){
            $http.post('/check_name',data).success(function(data, status, headers, config) {
                if( !data.msg ){
                    $scope.RegisterAlert = true;
                }else{
                    $scope.RegisterAlert = false;
                }
            }).error(function(data, status) {
                alert("Connection Error");
            });
        }
    }
});

3. Create a style sheet named style.css in the css/ directory inside view folder.

 style.css:
body {
    font-family: cursive;
    text-transform: uppercase;
	background-color: #F9F7F7;
}

/*--------------------------------------------------------------------------------
Normalize  starts
--------------------------------------------------------------------------------*/

h1,h2,h3,h4{
	color:#50d0c1;
}

a{
	color: #000;
	text-decoration: none;
}


a:visited {
	color: #000;
	text-decoration: none;
}

a:hover,
a:focus,
a:active {
	color: #000;
	text-decoration: none;
}
.container{
	width: 100%;
}
.close{
	color: #000 !important;
}
.modal-content{
	background-color:#F6F6F6;
	color: #000 !important;	
	height: 90%;
	overflow-y: scroll;
}
.modal-body{
	padding: 20px 100px;
}
.modal{
	background-color: rgba(20, 36, 44, 0.45);
}
.modal-dialog{
	width: 60%;
}
.modal-title{
	font-size: 20px;
}
.alert-danger{
	color: #fff;
	background-color:#F44336;
}

.userlist::-webkit-scrollbar {
    width: 12px;
}
.userlist::-webkit-scrollbar-track {
    background-color: #eaeaea;
    border-left: 1px solid #ccc;
}
.userlist::-webkit-scrollbar-thumb {
    background-color: #ccc;
}
.userlist::-webkit-scrollbar-thumb:hover {
    background-color: #aaa;
}
/*--------------------------------------------------------------------------------
Login page starts
--------------------------------------------------------------------------------*/
.index{
	z-index: 2;
	height: 100%;
	position: absolute;
	top: 0%;
}
.box-container{
	margin-top: 2%;
	width: 35%;
	height: 500px;
    display: block;
    padding: 50px;
    margin-left: 60%;
    border: solid 3px rgb(102, 224, 210);
    box-shadow: 0px 2px 100px 6px rgba(0,0,0,0.35);
	background-color:rgba(80, 208, 193, 0.77);
}

.heading{
	padding: 15px;
	text-align: center;
}
.box-container h2,h4 {
	color: #fff !important;
}
.iconbg,
.inputbg,
.btnbg{
	color: rgba(0, 0, 0, 0.58);
    border: solid 1px rgba(0, 0, 0, 0.58);
    background-color:#fff; 
}
div.p_photo-group {
    width: 80px;
    height: 60px;
    background: url(/img/upload.PNG);
    background-size: 80px 60px,cover;
    background-repeat: no-repeat;
    overflow: hidden;    
}
.p_photo{
	display: block !important;
    width: 80px !important;
    height: 60px !important;
    opacity: 0 !important;
    overflow: hidden !important;
}
.selectedFile{
	margin-bottom: 20px;
	color: #fff;
	font-size: 15px;
	font-weight: bolder;
}
.password-group,
.username-group,
.btnbg{
	margin-bottom: 25px;
}

.btnbg{
	width: 100%;
}
.btnbg:hover{
	color:#50d0c1;
	border: solid 1px rgba(0, 0, 0, 1);
}
.opr-loader{
	float: right;
}
.signup-box{
	text-align: center;
	margin-top:20px;
}
@media screen and (max-width: 700px) {
	.index{
		padding: 20px;
	}
	.box-container{
		margin: 0px auto;
		width: 50%;
	}

}
/*--------------------------------------------------------------------------------
Login page ends
--------------------------------------------------------------------------------*/

Till now, we have successfully built the login and registration page and created config files. 

In next part  we will create our home page. 

See you in next part.

  • tonado

    This chat is amazingly good. I just love it.

    • Thank You!

      • tonado

        can you please check your mail. I sent you a mail via your email contact for some kind of assistance. Thanks

  • Ladna Meke

    If your target audience is newbie/beginner (as you said), please do well to explain the code rather than just expect the newbie to figure out these intricacies.

    My two cents.

    • Sure I will take care of this thanks for pointing out.

  • Dwight Light

    mate, i haven’t even finished reading it and i’m loving it already…..

  • Avi Ku

    Its really very helpful man. thumps up

  • hellp, how to solution ?

  • help

    • Create one more column named as ‘online’ in ‘users’ table.
      Actually I forgot to give updated SQL Queries

      • ok, can you please give me updates the sql query

        • Run this query for ‘user’ table.

          Sql Query :
          ALTER TABLE user ADD online varchar(2)

          • ok, thank you very much

          • why the application can not run up like in the pictures in this article? ..

            when exiting an application like this:

  • Xanh Nước Biển

    That is great app, man.
    But I got a problem when try to run [+] to view START NEW CHAT.
    In this pop up, there are no Users.
    Please help me explain that how to view list Users in this popup ?

    • Actually, Query is taking too much time to fetch record from DB. Soon I will fix this issue.

      • Xanh Nước Biển

        Thank you, Shashank.
        I try to run DEMO, it can load list of users. Did you fix this issue ?
        Please share with me how to fix that ?

      • Xanh Nước Biển

        Sometime, when I log out, there is an error was through out like picture below.
        Please show to me how to fix that error.

  • gullele

    Thanks a lot, it just work out of the box so nicely. I am using it with vagrant and will be adding additional chat features and will share it back.
    Thanks for the great work and sharing it with us.

    http://gullele.com

  • Arvind Kumar Sinha

    Hi Shashank,
    Thank for your chat app, It will help me, but got a Connection error at login time, help me dear

    • gullele

      Hey Arvind,
      The connection error is most probably the mysql connection string that you have to adjust on middleware/db.js

      In that file you will see something like mysql.createPool and you have to add your own connection credential there and that would take care of the problem.

      • Arvind Kumar Sinha

        already tried but not susses. Can you create custom chat (text, audio, video) as per my project requirement.

  • Morm Sopheak

    Hi Shashank,

    I have tried to run your demo app. but it dosem’t work by showing these below error :

    file:///C:/Users/msopheak/Desktop/chat/views/js/auth-routes.js Failed to load resource: net::ERR_FILE_NOT_FOUND

    and I tried to fix it by changing the path of auth-routes.js to moddleware/auth-rotues.js
    but it showing one more problem like the below image

    auth-routes.js:3 Uncaught ReferenceError: require is not defined

    • To run nodejs app, first make sure u have installed NODEJS & Mysql (Xampp)

      1. open the directory where u have your nodejs application, copy the path now go to the CMD.

      2.Enter into that directory by writing cd command.

      3. Now write node server.js and your application should run properly.

      hope this helps.

  • prem

    Hi,

    Cannot find module ‘./lib/_stream_readable.js’…install lib my file readable_stream..But again show the error…can’t read stream_readable.js..

  • Voeun So

    Hello,When i run server.js still show this error why?can you help me please bro?

  • Voeun So

    Hello,I still show this error when i want to select to use to starting chat.i don’t know why? can you help me bro?

    • Mauri Cabrera Estrada

      SAME HERE!
      THE ISSUE APPEARS WHEN WE CHOOSE AN OFFLINE USER HELP!

      • Mauri Cabrera Estrada

        THIS IS THE ERROR THAT CONSOLE SHOWS!!!

        C:UsersMauriCDownloadsbackupschanode_modulesmysqllibprotocolParser.js:
        77
        throw err; // Rethrow non-MySQL errors
        ^
        TypeError: undefined is not a function
        at C:UsersMauriCDownloadsbackupschamiddlewareroutes.js:97:30
        at C:UsersMauriCDownloadsbackupschamiddlewarehelper.js:202:8
        at C:UsersMauriCDownloadsbackupschamiddlewarehelper.js:254:7
        at Query._callback (C:UsersMauriCDownloadsbackupschamiddlewarehelper.
        js:16:9)
        at Query.Sequence.end (C:UsersMauriCDownloadsbackupschanode_modulesmy
        sqllibprotocolsequencesSequence.js:96:24)
        at Query._handleFinalResultPacket (C:UsersMauriCDownloadsbackupschanod
        e_modulesmysqllibprotocolsequencesQuery.js:144:8)
        at Query.EofPacket (C:UsersMauriCDownloadsbackupschanode_modulesmysql
        libprotocolsequencesQuery.js:128:8)
        at Protocol._parsePacket (C:UsersMauriCDownloadsbackupschanode_modules
        mysqllibprotocolProtocol.js:280:23)
        at Parser.write (C:UsersMauriCDownloadsbackupschanode_modulesmysqlli
        bprotocolParser.js:73:12)
        at Protocol.write (C:UsersMauriCDownloadsbackupschanode_modulesmysql
        libprotocolProtocol.js:39:16)

        • Mauri Cabrera Estrada

          please help!!!

          • rian s

            check database name middleware/db.js make sure database name is same

  • rian s

    This app is amazing, very help me to create my thesis, thanks, Btw can you help me how to create a group chat?

    • In a group chat, You can use ‘io.emit()’ to send message to all users connected to socket instead of sending messages to specific user.

      More on Broadcasting messages : http://socket.io/docs/#broadcasting-messages

      • rian s

        i just cotomized your app shashank, but where i can live or hosting this app?

        • You have multiple options for ex. DigitalOcean , Heroku and RHCluoud (Openshift)
          & they have good documentation.

          • rian s

            Ok i will try, and then, why the contact isn’t appear in modal contact?

  • Adithya Nj

    hi ,i am getting the below error. please give solution and reason for the below error

    [Error: UNKNOWN_CODE_PLEASE_REPORT: Expression #1 of ORDER BY clause is not in SELECTlist, references column ‘chat.conversation.timestamp’ which is not in SELECT list; this is incompatible with DISTINCT]
    code: ‘UNKNOWN_CODE_PLEASE_REPORT’,
    errno: 3065,
    sqlState: ‘HY000’,
    index: 0 }
    Query failed
    { [Error: UNKNOWN_CODE_PLEASE_REPORT: Expression #1 of ORDER BY clause is not in SELECT list, references column ‘chat.conversation.timestamp’ which is not in SELECT list; this is incompatible with DISTINCT]
    code: ‘UNKNOWN_CODE_PLEASE_REPORT’,
    errno: 3065,
    sqlState: ‘HY000’,
    index: 0 }
    Query failed

  • Hkm Sadek Hossain

    Hi, Is it possible to use the socket session in other page? For example, let’s say you are in home page, an someone texted you from chat page. So is it possible to notify the person who is in home page and not in chat page??

    Currently, it let notify if both the person in the same chat page,

    Also, is it possible to get the sane feature without using angular and using jQuery

    • Sorry for late reply.
      Yes, is it possible give it a shot.

      and am not sure what you mean by ‘without using angular and using jQuery’ !
      As long as socket is concerned to get update from server, you will require socket library.

  • Ho Sy Quyet

    Hi, I tried settup this app in my localhost but “_userinfo Failed to load resource: the server responded with a status of 404 (Not Found)”, all route can not access. Please help me run success this app! thanks you!

  • Bozidar Atanasovski

    Am getting the following error $scope.msgs.push is not a function 🙁

  • iBlacklegend .

    If any one has insights it would be much appreciated.
    I have a relatively basic question. I have read through the first part of this tutorial and I have been able to follow along for the most part. I have a my own project that uses similar technology, and incorporates a login page. I am having a little trouble gluing everything together. Specifically I am confused how he has integrated Angular.js with his web server. A better example of what I mean, when his login-register contrller posts a login or a register request, how does his web server know to handle it, i.e why does his autu-routes class get triggered? I do not see any code telling it what URL or host to use. Can any explain why a post request gets automatically handled by his web server?

  • Syeda Kubra Fatima

    please can anyone help me. I am stuck in registration process. when I click the register after entering the requirements I get connection error. And console shows this
    https://uploads.disquscdn.com/images/de93049f597dbb8cac7eb7b1e426cb1a6272b1476baa7e67185a6af5ed480b9a.png

    • Juan Pablo Pola Demoro

      Did you try with admin privileges?

  • Prabhakar
    • Hi Prabhakar ,
      please make sure you are passing the app variable in a route function.

  • drashti

    https://uploads.disquscdn.com/images/dd0aef72abd42b3bb7d2e243b0e22525190d0ce1c9dfd3a920023bd9d6987f24.png

    hii shashank , i got continuasly alert of connection error please help me for further

    • Hi,

      Can you please post the error that you are getting in your console ?

      • drashti
        • Sorry for late reply drashti ,

          The reason for this error : con object is undefined

          On line number 202 in auth-route file.

          How to fix it :

          Make sure you are passing connection object to auth-route file in server.js.

          Then in auth-route file, you must receive that connection object as a parameter to run your mysql queries.

      • drashti

        please give me solution

  • Tayebe Hoseini

    hi your site doesn’t support resume for download? i can’t download it could you please solve this problem…
    or send it by email…
    thanks…

  • varun ajmera

    Conversation: This table holds the conversation Id between users.
    why do we need conversation id? @ShankyTtiwari:disqus

    • You are a true observer.
      For some reason I created that column and I think I forgot to remove that column please ignore I will update the code.

  • Diego Escobar Jordá

    Hi i’m trying to download, but it stops at half for some reason.. any idea why?

  • simo

    Hi … Thank you for your application and it work 100% … i want just add firstname and lastname in register page … can you please help me