AngularJS tutorial for beginners with NodeJS ExpressJS and MongoDB (Part I)

AngularJS tutorial for beginners with NodeJS ExpressJS and MongoDB (Part I)

This tutorial is meant to be as clear as possible. At the same time, we are going to cover the concepts that you will need most of the time. All the good stuff without the fat :)

This tutorial is meant to be as clear as possible. At the same time, we are going to cover the concepts that you will need most of the time. All the good stuff without the fat :)

MEAN Stack tutorial series:

  1. AngularJS tutorial for beginners (Part I) 👈 you are here
  2. Creating RESTful APIs with NodeJS and MongoDB Tutorial (Part II)
  3. MEAN Stack Tutorial: MongoDB, ExpressJS, AngularJS and NodeJS (Part III)

We are going to start building all the examples in a single HTML file! It embedded JavaScript and NO styles/CSS for simplicity. Don’t worry, in the next tutorials, we will learn how to split use Angular modules. We are going to break down the code, add testing to it and styles.

1. What is Angular.js?

Angular.js is a MVW (Model-View-Whatever) open-source JavaScript web framework that facilitates the creation of single-page applications (SPA) and data-driven apps.

1.1 AngularJS vs jQuery vs BackboneJS vs EmberJS

TL; DR: AngularJS is awesome for building testable single page applications (SPA). Also, excel with data-driven and CRUD apps. Show me the code!.

AngularJS motto is

HTML enhanced for web apps!
It extends standard HTML tags and properties to bind events and data into it using JavaScript. It has a different approach to other libraries. jQuery, Backbone.Js, Ember.js and similar… they are more leaned towards “Unobtrusive JavaScript”.

Traditional JavaScript frameworks, use IDs and classes in the elements. That gives the advantage of separating structure (HTML) from behavior (Javascript). Yet, it does not do any better on code complexity and readability. Angular instead declares the event handlers right in the element that they act upon.

Times have changed since then. Let’s examine how AngularJS tries to ease code complexity and readability:

  • Unit testing ready: JavaScript is, usually, hard to unit test. When you have DOM manipulations and business logic together (e.g. jQuery based code). AngularJS keeps DOM manipulation in the HTML and business logic separated. Data and dependencies are $injected as needed.
  • DOM manipulation where they are used. It decouples DOM manipulation from application logic.
  • AngularJS is also excellent for single-page applications (SPA).
  • Different browsers implement features differently, but fret not. Angular’s directive (or HTML extensions) take care of the differences for you.
  • Global namespace expressions and methods definitions are scoped within controllers. So, they do not pollute the global namespace.
  • Data models are plain old JavaScript objects (POJO).
  • Write less code: AngualarJS features save you from much boilerplate code.
  • AngularJS provides solutions for writing modular code and dependencies management.

Without further ado, let’s dive in!

2. AngularJS Main Components

AngularJS has an extensive API and components. In this tutorial we are going to focus on the most important ones, such as directives, modules, services, controllers and related concepts.

2.1 AngularJS Directives

The first concept you need to know about AngularJS is what are directives.

Directives are extensions of HTML markups. They could take the form of attributes, element names, CSS class and or even HTML comments. When the AngularJS framework is loaded, everything inside ng-app it’s compiled. The directives are bound to data, events, and DOM transformations.

Notice in the following example that there are two directives: ng-app and ng-model.

Notice in the following example that there are two directives: ng-app and ng-model.

Hello World in AngularJS
<html ng-app>
<head>
  <title>Hello World in AngularJS</title>
</head>
<body>

<input ng-model="name"> Hello {{ name }}

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
</body>
</html>

We going to learn about some of the main built-in directives as we go:

  • ng-app: is a directive that bootstraps AngularJS. It designates the caller element as the root. It’s usually placed on <html> or <body>.
  • ng-model: is a directive that binds usually form elements. For instance, input, select, checkboxes, textarea. They keep data (model) and visual elements (HTML) in sync.
  • {{ name }} {{ }} are a way of binding models to elements in HTML. In the example above, the ng-model name is bound to the placeholder {{ name }}. Play with the example below to see how the placeholder is updated real-time to whatever you type in the textbox.

Data binding AngularJS example:

You can create your own directives. Checkout the this tutorial for more: creating-custom-angularjs-directives-for-beginners. It will go deeper into directives.

2.2 AngularJS Data Binding

Data binding is an AngularJS feature that synchronizes your model data with your HTML. That’s great because models are the “single source of truth”. You do not have to worry about updating them. Here’s a graph from docs.angularjs.org.

Whenever the HTML is changed, the model gets updated. Wherever the model gets updated it is reflected in HTML.

2.3 AngularJS Scope

$scope it is an object that contains all the data to which HTML is bound. They are the glue your javascript code (controllers) and the view (HTML). Everything that is attached to the $scope, it is $watched by AngularJS and updated.

Scopes can be bound to javascript functions. Also, you could have more than one $scope and inherit from outer ones. More on this, in the controller’s section.

2.4 AngularJS Controllers

Angular.js controllers are code that “controls” certain sections containing DOM elements. They encapsulate the behavior, callbacks and glue $scope models with views. Let’s see an example to drive the concept home:

AngularJS Controller Example
 <body ng-controller="TodoController">
  <ul>
    <li ng-repeat="todo in todos">
      <input type="checkbox" ng-model="todo.completed">
      {% raw  %}{{ todo.name }}{% endraw %}
    </li>
  </ul>

  <script>
    function TodoController($scope){
      $scope.todos = [
        { name: 'Master HTML/CSS/Javascript', completed: true },
        { name: 'Learn AngularJS', completed: false },
        { name: 'Build NodeJS backend', completed: false },
        { name: 'Get started with ExpressJS', completed: false },
        { name: 'Setup MongoDB database', completed: false },
        { name: 'Be awesome!', completed: false },
      ]
    }
  </script>
</body>

AngularJS controller interactive example:

As you might notice we have new friends: ng-controller, ng-repeat and $scope.

  • <strong>ng-controller</strong> is a directive that tells angular what function controller to use for a particular view. Every time AngularJS loads, it reads the ng-controller argument (in this case “TodoController”). Then, it will look for a function in plain old javascript object (POJO) with the same name or for angular.controller matching name.
  • <strong>$scope</strong> As mentioned earlier $scope‘s are the glue between the data models in the controllers and the views. Take a look to our “TodoController” it has a parameter named $scope. AngularJS is going to pass ($inject) that parameter, and whatever you attach to it, it will be available in the view. In this example is the particular is the todos array of objects.
  • <strong>ng-repeat</strong> as its name implies, it is going to “repeat” the element and sub-elements where this directive is declared. It is going to iterate for each element in the $scope.todos array.
  • <strong>ng-model</strong> notice that the checkbox is bound to the todo.completed. If todo.completedis true, then the checkbox is going to be checked and vice versa.
2.5 AngularJS Modules

Modules are a way to encapsulate different parts of your application. They allow reusing code in other places. Here’s an example of how to rewrite our controller using modules.

AngularJS Module Example

angular.module('app', [])
  .controller('TodoController', ['$scope', function ($scope) {
    $scope.todos = [
      { title: 'Learn Javascript', completed: true },
      { title: 'Learn Angular.js', completed: false },
      { title: 'Love this tutorial', completed: true },
      { title: 'Learn Javascript design patterns', completed: false },
      { title: 'Build Node.js backend', completed: false },
    ];
  }]);

Notice the <html ng-app="app"> in the example below

Using modules brings many advantages. They can be loaded in any order, and parallel dependency loading. Also, tests can only load the required modules and keep it fast, clear view of the dependencies.

2.6 AngularJS Templates

Templates contain HTML and Angular elements (directives, markup, filters or form controls). They can be cached and referenced by an id.

Here’s an example:

AngularJS Template Example

<script type="text/ng-template" id="/todos.html">
  <ul>
    <li ng-repeat="todo in todos">
      <input type="checkbox" ng-model="todo.completed">
      {{ todo.name }}
    </li>
  </ul>
</script>

Does the code inside looks familiar? ;)

Notice they are inside the script and has a type of text/ng-template.

AngularJS Routes (ngRoutes)

ngRoutes module allows changing what we see in the app depending on the URL (route). It, usually, uses templates to inject the HTML into the app.

It does not come with AngularJS core module, so we have to list it as a dependency. We are going to get it from Google CDN:

<script src="<a href="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.min.js"></script>" target="_blank">https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.min.js"></script></a>

NEW FEATURE: add notes to the todo tasks. Let’s start with the routes!

angular.module('app', ['ngRoute'])
  .config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/', {
        templateUrl: '/todos.html',
        controller: 'TodoController'
      });
  }]);

  • First notice that we removed ng-controller="TodoController" from the body tag. The controllers are now called based on the route.
  • ngView is a directive used by $routeProvider to render HTML into it. Every time the URL changes, it will inject a new HTML template and controller into ngView.
2.8 AngularJS Services (Factories)

Notice that if you want to create a 2nd controller and share $scope.todos it is not possible right now. That is when services become handy. Services are a way to inject data dependencies into controllers. They are created through factories. Let’s see it in action:

AngularJS Service Factory Example

 angular.module('app', ['ngRoute'])

  .factory('Todos', function(){
    return [
      { name: 'AngularJS Directives', completed: true },
      { name: 'Data binding', completed: true },
      { name: '$scope', completed: true },
      { name: 'Controllers and Modules', completed: true },
      { name: 'Templates and routes', completed: true },
      { name: 'Filters and Services', completed: false },
      { name: 'Get started with Node/ExpressJS', completed: false },
      { name: 'Setup MongoDB database', completed: false },
      { name: 'Be awesome!', completed: false },
    ];
  })

  .controller('TodoController', ['$scope', 'Todos', function ($scope, Todos) {
    $scope.todos = Todos;
  }])

We are now injecting the data dependency Todo into the controllers. This way we could reuse the data to any controller or module that we need to. This is not only used for static data like the array. But we could also do server calls using $http or even RESTful $resource.

Let’s say we want to show the details of the task when we click on it. For that, we need to create a 2nd controller, template, and route that uses this service:

(NOTE: Click on the links and it will take you to the todo details. Use backspace key to go back to the main menu)

This is what is happening:

  1. In the HTML tab, we created a second template /todoDetails.html which contains the todo details we want to show.
  2. Also, in our previous template /todos.html we want to have a link that points to the tododetail. We are using the $index which is the corresponding order number in a ng-repeat.
  3. In the JS tab, we created a new $routeProvider . It points to a new controller TodoDetailCtrl and the template that we created on #1. The :id parameter it is accessible in the controllers through $routeParams.
  4. We Created the new controller TodoDetailCtrl. Also, we injected the dependencies which are $scope, Todos (factory), and $routeParams which will have the id param.
  5. Set the $scope in the new controller. Instead of using the whole array, we are going to select only the one that we need using the id that we set in step #2.

NOTE: in codepen, you will not see the URL. If you want to see it changing, you can download the whole example an open it from here.

2.9 AngularJS Filters

Filters allow you to format and transform data. They change the output of expressions inside the curly braces. AngularJS comes with a bunch of useful filters.

Built-in Filters:

  • filter: search for a given string in an array and return matches.
  • Number: adds comma-separated 1000’s and two decimal places.
  • Currency: the same as Number and adds a $ in front.
  • Date: takes a Unix timestamp (e.g. 1288323623006) or date string and output it in the format that you specify (e.g. ‘longDate’ or fragments ‘yyyy’ for a four-digit year). For a full list see here.
  • JSON: converts javascript objects to JSON strings.
  • lowercase/uppercase: converts strings to lowercase/uppercase.
  • limitTo: number of elements from an array to show.
  • orderBy: order array of objects by a key that you specify.

Note you can also chain many filters and also define your own filters.

NEW FEATURE: Search todo tasks by name. Let’s use a filter to solve that problem.

<script type="text/ng-template" id="/todos.html">
  Search: <input type="text" ng-model="search.name">
  <ul>
    <li ng-repeat="todo in todos | filter: search">
      <input type="checkbox" ng-model="todo.completed">
      <a href="#/{{$index}}">{{todo.name}}</a>
    </li>
  </ul>
</script>

Notice that we are using search.name in the ng-model for search. That will limit the search to the name attribute and search.notes will look inside the notes only. Guest what search would do then? Precisely! It searches in all the attributes. Fork the following example and try it out:

3.What’s next?

Congrats! You have completed part 1 of this 3 part series. We are going to build upon the things learned in here, in the next post we are going to setup a backend in NodeJS and MongoDB and connect it to AngularJS to provide a full featured CRUD app. Continue with:

I also have created BackboneJS tutorials check it out:

ng-test

Congrats, you have reached this far! It is time to test what you have learned. Test-Driven Learning (TDL) ;). Here’s the challenge: open this file on your favorite code editor. Copy the boilerplate code and built the full app that we just build in the previous examples. Of course, you can take a peek from time to time if you get stuck ;)

Download this file as…:

index.html

-OR-

Fork and edit online:

ng-solution

This is the full solution and you can see it live in here.

<html ng-app="app">
	<head>
	  <title>ngTodo</title>
	</head>
	<body>
	

	<ng-view></ng-view>
	

	<!-- Libraries -->
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular.min.js"></script>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.25/angular-route.min.js"></script>
	

	<!-- Template -->
	<script type="text/ng-template" id="/todos.html">
	  Search: <input type="text" ng-model="search.name">
	  <ul>
	    <li ng-repeat="todo in todos | filter: search">
	      <input type="checkbox" ng-model="todo.completed">
	      <a href="#/{{$index}}">{{todo.name}}</a>
	    </li>
	  </ul>
	</script>
	

	<script type="text/ng-template" id="/todoDetails.html">
	  <h1>{{ todo.name }}</h1>
	  completed: <input type="checkbox" ng-model="todo.completed">
	  note: <textarea>{{ todo.note }}</textarea>
	</script>
	

	<script>
	  angular.module('app', ['ngRoute'])
	
	    //---------------
	    // Services
	    //---------------
	
	    .factory('Todos', function(){
	      return [
	        { name: 'AngularJS Directives', completed: true, note: 'add notes...' },
	        { name: 'Data binding', completed: true, note: 'add notes...' },
	        { name: '$scope', completed: true, note: 'add notes...' },
	        { name: 'Controllers and Modules', completed: true, note: 'add notes...' },
	        { name: 'Templates and routes', completed: true, note: 'add notes...' },
	        { name: 'Filters and Services', completed: false, note: 'add notes...' },
	        { name: 'Get started with Node/ExpressJS', completed: false, note: 'add notes...' },
	        { name: 'Setup MongoDB database', completed: false, note: 'add notes...' },
	        { name: 'Be awesome!', completed: false, note: 'add notes...' },
	      ];
	    })
	
	    //---------------
	    // Controllers
	    //---------------
	
	    .controller('TodoController', ['$scope', 'Todos', function ($scope, Todos) {
	      $scope.todos = Todos;
	    }])
	
	    .controller('TodoDetailCtrl', ['$scope', '$routeParams', 'Todos', function ($scope, $routeParams, Todos) {
	      $scope.todo = Todos[$routeParams.id];
	    }])
	
	    //---------------
	    // Routes
	    //---------------
	
	    .config(['$routeProvider', function ($routeProvider) {
	      $routeProvider
	        .when('/', {
	          templateUrl: '/todos.html',
	          controller: 'TodoController'
	        })
	
	        .when('/:id', {
	          templateUrl: '/todoDetails.html',
	          controller: 'TodoDetailCtrl'
	       });
	    }]);
	</script>
	

	</body>
	</html>

How to Use Express.js, Node.js and MongoDB.js

How to Use Express.js, Node.js and MongoDB.js

In this post, I will show you how to use Express.js, Node.js and MongoDB.js. We will be creating a very simple Node application, that will allow users to input data that they want to store in a MongoDB database. It will also show all items that have been entered into the database.

In this post, I will show you how to use Express.js, Node.js and MongoDB.js. We will be creating a very simple Node application, that will allow users to input data that they want to store in a MongoDB database. It will also show all items that have been entered into the database.

Creating a Node Application

To get started I would recommend creating a new database that will contain our application. For this demo I am creating a directory called node-demo. After creating the directory you will need to change into that directory.

mkdir node-demo
cd node-demo

Once we are in the directory we will need to create an application and we can do this by running the command
npm init

This will ask you a series of questions. Here are the answers I gave to the prompts.

The first step is to create a file that will contain our code for our Node.js server.

touch app.js

In our app.js we are going to add the following code to build a very simple Node.js Application.

var express = require("express");
var app = express();
var port = 3000;
 
app.get("/", (req, res) => {
&nbsp;&nbsp;res.send("Hello World");
});
 
app.listen(port, () => {
  console.log("Server listening on port " + port);
});

What the code does is require the express.js application. It then creates app by calling express. We define our port to be 3000.

The app.use line will listen to requests from the browser and will return the text “Hello World” back to the browser.

The last line actually starts the server and tells it to listen on port 3000.

Installing Express

Our app.js required the Express.js module. We need to install express in order for this to work properly. Go to your terminal and enter this command.

npm install express --save

This command will install the express module into our package.json. The module is installed as a dependency in our package.json as shown below.

To test our application you can go to the terminal and enter the command

node app.js

Open up a browser and navigate to the url http://localhost:3000

You will see the following in your browser

Creating Website to Save Data to MongoDB Database

Instead of showing the text “Hello World” when people view your application, what we want to do is to show a place for user to save data to the database.

We are going to allow users to enter a first name and a last name that we will be saving in the database.

To do this we will need to create a basic HTML file. In your terminal enter the following command to create an index.html file.

touch index.html

In our index.html file we will be creating an input filed where users can input data that they want to have stored in the database. We will also need a button for users to click on that will add the data to the database.

Here is what our index.html file looks like.

<!DOCTYPE html>
<html>
  <head>
    <title>Intro to Node and MongoDB<title>
  <head>

  <body>
    <h1>Into to Node and MongoDB<&#47;h1>
    <form method="post" action="/addname">
      <label>Enter Your Name<&#47;label><br>
      <input type="text" name="firstName" placeholder="Enter first name..." required>
      <input type="text" name="lastName" placeholder="Enter last name..." required>
      <input type="submit" value="Add Name">
    </form>
  <body>
<html>

If you are familiar with HTML, you will not find anything unusual in our code for our index.html file. We are creating a form where users can input their first name and last name and then click an “Add Name” button.

The form will do a post call to the /addname endpoint. We will be talking about endpoints and post later in this tutorial.

Displaying our Website to Users

We were previously displaying the text “Hello World” to users when they visited our website. Now we want to display our html file that we created. To do this we will need to change the app.use line our our app.js file.

We will be using the sendFile command to show the index.html file. We will need to tell the server exactly where to find the index.html file. We can do that by using a node global call __dirname. The __dirname will provide the current directly where the command was run. We will then append the path to our index.html file.

The app.use lines will need to be changed to
app.use("/", (req, res) => {   res.sendFile(__dirname + "/index.html"); });

Once you have saved your app.js file, we can test it by going to terminal and running node app.js

Open your browser and navigate to “http://localhost:3000”. You will see the following

Connecting to the Database

Now we need to add our database to the application. We will be connecting to a MongoDB database. I am assuming that you already have MongoDB installed and running on your computer.

To connect to the MongoDB database we are going to use a module called Mongoose. We will need to install mongoose module just like we did with express. Go to your terminal and enter the following command.
npm install mongoose --save

This will install the mongoose model and add it as a dependency in our package.json.

Connecting to the Database

Now that we have the mongoose module installed, we need to connect to the database in our app.js file. MongoDB, by default, runs on port 27017. You connect to the database by telling it the location of the database and the name of the database.

In our app.js file after the line for the port and before the app.use line, enter the following two lines to get access to mongoose and to connect to the database. For the database, I am going to use “node-demo”.

var mongoose = require("mongoose"); mongoose.Promise = global.Promise; mongoose.connect("mongodb://localhost:27017/node-demo");

Creating a Database Schema

Once the user enters data in the input field and clicks the add button, we want the contents of the input field to be stored in the database. In order to know the format of the data in the database, we need to have a Schema.

For this tutorial, we will need a very simple Schema that has only two fields. I am going to call the field firstName and lastName. The data stored in both fields will be a String.

After connecting to the database in our app.js we need to define our Schema. Here are the lines you need to add to the app.js.
var nameSchema = new mongoose.Schema({   firstName: String,   lastNameName: String });

Once we have built our Schema, we need to create a model from it. I am going to call my model “DataInput”. Here is the line you will add next to create our mode.
var User = mongoose.model("User", nameSchema);

Creating RESTful API

Now that we have a connection to our database, we need to create the mechanism by which data will be added to the database. This is done through our REST API. We will need to create an endpoint that will be used to send data to our server. Once the server receives this data then it will store the data in the database.

An endpoint is a route that our server will be listening to to get data from the browser. We already have one route that we have created already in the application and that is the route that is listening at the endpoint “/” which is the homepage of our application.

HTTP Verbs in a REST API

The communication between the client(the browser) and the server is done through an HTTP verb. The most common HTTP verbs are
GET, PUT, POST, and DELETE.

The following table explains what each HTTP verb does.

HTTP Verb Operation
GET Read
POST Create
PUT Update
DELETE Delete

As you can see from these verbs, they form the basis of CRUD operations that I talked about previously.

Building a CRUD endpoint

If you remember, the form in our index.html file used a post method to call this endpoint. We will now create this endpoint.

In our previous endpoint we used a “GET” http verb to display the index.html file. We are going to do something very similar but instead of using “GET”, we are going to use “POST”. To get started this is what the framework of our endpoint will look like.

app.post("/addname", (req, res) => {
 
});
Express Middleware

To fill out the contents of our endpoint, we want to store the firstName and lastName entered by the user into the database. The values for firstName and lastName are in the body of the request that we send to the server. We want to capture that data, convert it to JSON and store it into the database.

Express.js version 4 removed all middleware. To parse the data in the body we will need to add middleware into our application to provide this functionality. We will be using the body-parser module. We need to install it, so in your terminal window enter the following command.

npm install body-parser --save

Once it is installed, we will need to require this module and configure it. The configuration will allow us to pass the data for firstName and lastName in the body to the server. It can also convert that data into JSON format. This will be handy because we can take this formatted data and save it directly into our database.

To add the body-parser middleware to our application and configure it, we can add the following lines directly after the line that sets our port.

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Saving data to database

Mongoose provides a save function that will take a JSON object and store it in the database. Our body-parser middleware, will convert the user’s input into the JSON format for us.

To save the data into the database, we need to create a new instance of our model that we created early. We will pass into this instance the user’s input. Once we have it then we just need to enter the command “save”.

Mongoose will return a promise on a save to the database. A promise is what is returned when the save to the database completes. This save will either finish successfully or it will fail. A promise provides two methods that will handle both of these scenarios.

If this save to the database was successful it will return to the .then segment of the promise. In this case we want to send text back the user to let them know the data was saved to the database.

If it fails it will return to the .catch segment of the promise. In this case, we want to send text back to the user telling them the data was not saved to the database. It is best practice to also change the statusCode that is returned from the default 200 to a 400. A 400 statusCode signifies that the operation failed.

Now putting all of this together here is what our final endpoint will look like.

app.post("/addname", (req, res) => {
  var myData = new User(req.body);
  myData.save()
    .then(item => {
      res.send("item saved to database");
    })
    .catch(err => {
      res.status(400).send("unable to save to database");
    });
});
Testing our code

Save your code. Go to your terminal and enter the command node app.js to start our server. Open up your browser and navigate to the URL “http://localhost:3000”. You will see our index.html file displayed to you.

Make sure you have mongo running.

Enter your first name and last name in the input fields and then click the “Add Name” button. You should get back text that says the name has been saved to the database like below.

Access to Code

The final version of the code is available in my Github repo. To access the code click here. Thank you for reading !

MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat App

MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat App

The comprehensive tutorial on MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat Application

The comprehensive tutorial on MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat Application

MEVN Tutorial: The comprehensive tutorial on MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat Application. Previously we have a tutorial on build chat application using MEAN Stack, now we build this chat application using MEVN (MongoDB, Express.js, Vue.js 2, Node.js) Stack. The different just now we use Vue.js 2 and Axios, we keep using MongoDB, Node.js, Express, and Socket.io.

Table of Contents:
  • Create a New Vue.js 2 Application using Vue-CLI
  • Install Express.js as RESTful API Server
  • Install and Configure Mongoose.js
  • Create REST API for Accessing Chat Data
  • Create Mongoose.js Model for Room and Chat
  • Create Vue.js 2 Component and Routing
  • Add Module for RESTful API Access and Styling UI
  • Modify Vue.js 2 Component for Room List
  • Modify Vue.js 2 Component for Add Room
  • Modify Vue.js 2 Component for Join Room
  • Modify Vue.js 2 Component for Chat Room
  • Integrate Socket.io With Existing Non-Real-time Chat Application
  • Run and Test The Chat Application

The scenario is very simple, just the rooms and the chats for each room. The first page will show the list of the rooms. After the user enters the room and fills the username or nickname then the user enters the chats with other users.

.The following tools, frameworks, and modules are required for this tutorial:

  1. Node.js (use recommended version)
  2. Express.js
  3. MongoDB
  4. Mongoose.js
  5. Vue.js
  6. Vue-CLI
  7. Socket IO
  8. Axios
  9. Terminal (Mac/Linux) or Node.js Command Line (Windows)
  10. IDE or Text Editor (we use Atom)

We assume that you have already installed Node.js and able to run Node.js command line (Windows) or npm on the terminal (MAC/Linux). Open the terminal or Node command line then type this command to install vue-cli.

sudo npm install -g vue-cli

That where we start the tutorial. We will create the MEVN stack Chat application using vue-cli.

1. Create a New Vue.js 2 Application using Vue-CLI

To create a new Vue.js 2 application using vue-cli simply type this command from terminal or Node command line.

vue init webpack mevn-chat

There will be a lot of questions, just leave it as default by always pressing enter key. Next, go to the newly created Vue.js project folder then install all default required modules by type this command.

cd ./mevn-chat

Now, check the Vue.js 2 application by running the application using this command.

npm run dev

Open your browser then go to localhost:8080 and you should see this page when everything still on the track.

2. Install Express.js as RESTful API Server

Close the running Vue.js 2 app first by press ctrl+c then type this command for adding Express.js modules and its dependencies.

npm install --save express body-parser morgan body-parser serve-favicon

Next, create a new folder called bin then add a file called www on the root of the Vue.js project folder.

mkdir bin
touch bin/www

Open and edit www file then add these lines of codes that contains configuration for an HTTP server, PORT, and error handling.

#!/usr/bin/env node

/**
 * Module dependencies.
 */

var app = require('../app');
var debug = require('debug')('mean-app:server');
var http = require('http');

/**
 * Get port from environment and store in Express.
 */

var port = normalizePort(process.env.PORT || '3000');
app.set('port', port);

/**
 * Create HTTP server.
 */

var server = http.createServer(app);

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

/**
 * Normalize a port into a number, string, or false.
 */

function normalizePort(val) {
  var port = parseInt(val, 10);

  if (isNaN(port)) {
    // named pipe
    return val;
  }

  if (port >= 0) {
    // port number
    return port;
  }

  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */

function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  var bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */

function onListening() {
  var addr = server.address();
  var bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

Next, change the default server what run by npm command. Open and edit package.json then replace startvalue inside scripts.

"scripts": {
  "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
  "start": "npm run build && node ./bin/www",
  "unit": "jest --config test/unit/jest.conf.js --coverage",
  "e2e": "node test/e2e/runner.js",
  "test": "npm run unit && npm run e2e",
  "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
  "build": "node build/build.js"
},

Next, create app.js in the root of project folder.

touch app.js

Open and edit app.js then add this lines of codes.

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var bodyParser = require('body-parser');

var room = require('./routes/room');
var chat = require('./routes/chat');
var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({'extended':'false'}));
app.use(express.static(path.join(__dirname, 'dist')));
app.use('/rooms', express.static(path.join(__dirname, 'dist')));
app.use('/api/room', room);
app.use('/api/chat', chat);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

Next, create routes folder then create routes file for the room and chat.

mkdir routes
touch routes/room.js
touch routes/chat.js

Open and edit routes/room.js file then add this lines of codes.

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.send('Express RESTful API');
});

module.exports = router;

Do the same way with routes/chat.js. Now, run the server using this command.

npm start

You will see the previous Vue.js landing page when you point your browser to [http://localhost:3000](http://localhost:3000 "http://localhost:3000"). When you change the address to [http://localhost:3000/api/room](http://localhost:3000/api/room "http://localhost:3000/api/room") or [http://localhost:3000/api/chat](http://localhost:3000/api/chat "http://localhost:3000/api/chat") you will see this page.

3. Install and Configure Mongoose.js

We need to access data from MongoDB. For that, we will install and configure Mongoose.js. On the terminal type this command after stopping the running Express server.

npm install --save mongoose bluebird

Open and edit app.js then add this lines after another variable line.

var mongoose = require('mongoose');
mongoose.Promise = require('bluebird');
mongoose.connect('mongodb://localhost/mevn-chat', { promiseLibrary: require('bluebird') })
  .then(() =>  console.log('connection succesful'))
  .catch((err) => console.error(err));

Now, run MongoDB server on different terminal tab or command line or run from the service.

mongod

Next, you can test the connection to MongoDB run again the Node application and you will see this message on the terminal.

connection succesful

If you are still using built-in Mongoose Promise library, you will get this deprecated warning on the terminal.

(node:42758) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html

That’s the reason why we added bluebird modules and register it as Mongoose Promise library.

4. Create Mongoose.js Model for Room and Chat

Add a models folder on the root of project folder for hold Mongoose.js model files then add Javascript file for Room and Chat.

mkdir models
touch models/Room.js
touch models/Chat.js

Next, open and edit models/Room.js then add this lines of codes.

var mongoose = require('mongoose'), Schema = mongoose.Schema;

var RoomSchema = new mongoose.Schema({
  room_name: String,
  created_date: { type: Date, default: Date.now },
});

module.exports = mongoose.model('Room', RoomSchema);

Open and edit models/Chat.js then add this lines of codes.

var mongoose = require('mongoose'), Schema = mongoose.Schema;

var ChatSchema = new mongoose.Schema({
  room : { type: Schema.Types.ObjectId, ref: 'Room' },
  nickname: String,
  message: String,
  created_date: { type: Date, default: Date.now },
});

module.exports = mongoose.model('Chat', ChatSchema);
5. Create Vue.js Component and Routing

Open and edit again routes/room.js then replace all codes with this.

var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Room = require('../models/Room.js');

/* GET ALL ROOMS */
router.get('/', function(req, res, next) {
  Room.find(function (err, products) {
    if (err) return next(err);
    res.json(products);
  });
});

/* GET SINGLE ROOM BY ID */
router.get('/:id', function(req, res, next) {
  Room.findById(req.params.id, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* SAVE ROOM */
router.post('/', function(req, res, next) {
  Room.create(req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* UPDATE ROOM */
router.put('/:id', function(req, res, next) {
  Room.findByIdAndUpdate(req.params.id, req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* DELETE ROOM */
router.delete('/:id', function(req, res, next) {
  Room.findByIdAndRemove(req.params.id, req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

module.exports = router;

Open and edit again routes/chat.js then replace all codes with this.

var express = require('express');
var router = express.Router();
var mongoose = require('mongoose');
var Chat = require('../models/Chat.js');

/* GET ALL CHATS */
router.get('/', function(req, res, next) {
  Chat.find(function (err, products) {
    if (err) return next(err);
    res.json(products);
  });
});

/* GET SINGLE CHAT BY ID */
router.get('/:id', function(req, res, next) {
  Chat.findById(req.params.id, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* SAVE CHAT */
router.post('/', function(req, res, next) {
  Chat.create(req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* UPDATE CHAT */
router.put('/:id', function(req, res, next) {
  Chat.findByIdAndUpdate(req.params.id, req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

/* DELETE CHAT */
router.delete('/:id', function(req, res, next) {
  Chat.findByIdAndRemove(req.params.id, req.body, function (err, post) {
    if (err) return next(err);
    res.json(post);
  });
});

module.exports = router;

Run again the Express server then open the other terminal or command line to test the Restful API by type this command.

curl -i -H "Accept: application/json" localhost:3000/api/room

If that command return response like below then REST API is ready to go.

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 2
ETag: W/"2-l9Fw4VUO7kr8CvBlt4zaMCqXZ0w"
Date: Sun, 05 Aug 2018 13:11:30 GMT
Connection: keep-alive

[]

Now, let’s populate Room collection with initial data that sent from RESTful API. Run this command to populate it.

curl -i -X POST -H "Content-Type: application/json" -d '{ "room_name":"Javascript" }' localhost:3000/api/room

You will see this response to the terminal if success.

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 109
ETag: W/"6d-OGpcih/JWvJGrYAhMP+KBYQOvNQ"
Date: Sun, 05 Aug 2018 13:35:50 GMT
Connection: keep-alive

{"_id":"5b66fd3581b9291558dc90b7","room_name":"Javascript","created_date":"2018-08-05T13:35:49.803Z","__v":0}

6. Create Vue.js 2 Component and Routing

Now, it’s time for Vue.js 2 or front end part. First, create or add the component of the room list, add a room, join a room, chat room. Create all of those files into the components folder.

touch src/components/RoomList.vue
touch src/components/AddRoom.vue
touch src/components/JoinRoom.vue
touch src/components/ChatRoom.vue

Now, open and edit src/router/index.js then add the import for all above new components.

import Vue from 'vue'
import Router from 'vue-router'
import RoomList from '@/components/RoomList'
import AddRoom from '@/components/AddRoom'
import JoinRoom from '@/components/JoinRoom'
import ChatRoom from '@/components/ChatRoom'

Add the router to each component or page.

export default new Router({
  routes: [
    {
      path: '/',
      name: 'RoomList',
      component: RoomList
    },
    {
      path: '/add-room',
      name: 'AddRoom',
      component: AddRoom
    },
    {
      path: '/join-room/:id',
      name: 'JoinRoom',
      component: JoinRoom
    },
    {
      path: '/chat-room/:id/:nickname',
      name: 'ChatRoom',
      component: ChatRoom
    }
  ]
})

7. Add Axios and Bootstrap-Vue

For UI or styling, we are using Bootstrap Vue. BootstrapVue use to build responsive, mobile-first projects on the web using Vue.js and the world's most popular front-end CSS library Bootstrap v4. To install Bootstrap-Vue type this command on the terminal.

npm i bootstrap-vue [email protected]

Open and edit src/main.js then add the imports for Bootstrap-Vue.

import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import App from './App'
import router from './router'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'

Add this line after Vue.config.

Vue.use(BootstrapVue)

Next, we are using Axio for accessing REST API provided by Express.js. Axios is a promise-based HTTP client for the browser and node.js. To install it, in the terminal type this command.

npm install axios --save

8. Modify Vue.js 2 Component for Room List

Now, open and edit src/components/RoomList.vue then add this lines of codes.

<template>
  <b-row>
    <b-col cols="12">
      <h2>
        Room List
        <b-link href="#/add-room">(Add Room)</b-link>
      </h2>
      <b-table striped hover :items="rooms" :fields="fields">
        <template slot="actions" scope="row">
          <b-btn size="sm" @click.stop="join(row._id)">Join</b-btn>
        </template>
      </b-table>
      <ul v-if="errors && errors.length">
        <li v-for="error of errors">
          {{error.message}}
        </li>
      </ul>
    </b-col>
  </b-row>
</template>

<script>

import axios from 'axios'

export default {
  name: 'BookList',
  data () {
    return {
      fields: {
        room_name: { label: 'Room Name', sortable: true, 'class': 'text-center' },
        created_date: { label: 'Created Date', sortable: true },
        actions: { label: 'Action', 'class': 'text-center' }
      },
      rooms: [],
      errors: []
    }
  },
  created () {
    axios.get(`http://localhost:3000/api/room`)
    .then(response => {
      this.rooms = response.data
    })
    .catch(e => {
      this.errors.push(e)
    })
  },
  methods: {
    join (id) {
      this.$router.push({
        name: 'JoinRoom',
        params: { id: id }
      })
    }
  }
}
</script>

There are template and script in one file. The template block contains HTML tags. Script block contains variables, page lifecycle and methods or functions.

9. Modify Vue.js 2 Component for Add Room

Now, open and edit src/components/AddRoom.vue then add this lines of codes.

<template>
  <b-row>
    <b-col align-self="start">&nbsp;</b-col>
    <b-col cols="6" align-self="center">
      <h2>
        Add Room
        <b-link href="#/">(Room List)</b-link>
      </h2>
      <b-form @submit="onSubmit">
        <b-form-group id="fieldsetHorizontal"
                  horizontal
                  :label-cols="4"
                  breakpoint="md"
                  label="Enter Room Name">
          <b-form-input id="room_name" :state="state" v-model.trim="room.room_name"></b-form-input>
        </b-form-group>
        <b-button type="submit" variant="primary">Save</b-button>
      </b-form>
    </b-col>
    <b-col align-self="end">&nbsp;</b-col>
  </b-row>
</template>

<script>

import axios from 'axios'

export default {
  name: 'AddRoom',
  data () {
    return {
      room: {}
    }
  },
  methods: {
    onSubmit (evt) {
      evt.preventDefault()
      axios.post(`http://localhost:3000/api/room`, this.room)
      .then(response => {
        this.$router.push({
          name: 'RoomList'
        })
      })
      .catch(e => {
        this.errors.push(e)
      })
    }
  }
}
</script>

That code contains the template for room form, the script that contains Vue.js 2 codes for hold room model and methods for saving room to RESTful API.

10. Modify Vue.js 2 Component for Join Room

Now, open and edit src/components/JoinRoom.vue then add this lines of codes.

<template>
  <b-row>
    <b-col cols="6">
      <h2>
        Join Room
        <b-link href="#/">(Room List)</b-link>
      </h2>
      <b-form @submit="onSubmit">
        <b-form-group id="fieldsetHorizontal"
                  horizontal
                  :label-cols="4"
                  breakpoint="md"
                  label="Enter Nickname">
          <b-form-input id="nickname" :state="state" v-model.trim="chat.nickname"></b-form-input>
        </b-form-group>
        <b-button type="submit" variant="primary">Join</b-button>
      </b-form>
    </b-col>
  </b-row>
</template>

<script>

import axios from 'axios'

export default {
  name: 'JoinRoom',
  data () {
    return {
      chat: {}
    }
  },
  methods: {
    onSubmit (evt) {
      evt.preventDefault()
      this.chat.room = this.$route.params.id
      this.chat.message = this.chat.nickname + ' join the room'
      axios.post(`http://localhost:3000/api/chat`, this.chat)
      .then(response => {
        this.$router.push({
          name: 'ChatRoom',
          params: { id: this.$route.params.id, nickname: response.data.nickname }
        })
      })
      .catch(e => {
        this.errors.push(e)
      })
    }
  }
}
</script>

That code contains the template for join room form, the script that contains Vue.js 2 codes for hold chat model and methods for saving room to RESTful API.

11. Modify Vue.js 2 Component for Chat Room

Now, open and edit src/components/JoinRoom.vue then add this lines of codes.

<template>
  <b-row>
    <b-col cols="12">
      <h2>
        Chat Room
      </h2>
      <b-list-group class="panel-body">
        <b-list-group-item v-for="(item, index) in chats" class="chat">
          <div class="left clearfix" v-if="item.nickname === nickname">
            <b-img left src="http://placehold.it/50/55C1E7/fff&text=ME" rounded="circle" width="75" height="75" alt="img" class="m-1" />
            <div class="chat-body clearfix">
              <div class="header">
                <strong class="primary-font">{{ item.nickname }}</strong> <small class="pull-right text-muted">
                <span class="glyphicon glyphicon-time"></span>{{ item.created_date }}</small>
              </div>
              <p>{{ item.message }}</p>
            </div>
          </div>
          <div class="right clearfix" v-else>
            <b-img right src="http://placehold.it/50/55C1E7/fff&text=U" rounded="circle" width="75" height="75" alt="img" class="m-1" />
            <div class="chat-body clearfix">
              <div class="header">
                <strong class="primary-font">{{ item.nickname }}</strong> <small class="pull-right text-muted">
                <span class="glyphicon glyphicon-time"></span>{{ item.created_date }}</small>
              </div>
              <p>{{ item.message }}</p>
            </div>
          </div>
        </b-list-group-item>
      </b-list-group>
      <ul v-if="errors && errors.length">
        <li v-for="error of errors">
          {{error.message}}
        </li>
      </ul>
      <b-form @submit="onSubmit" class="chat-form">
        <b-input-group prepend="Message">
          <b-form-input id="message" :state="state" v-model.trim="chat.message"></b-form-input>
          <b-input-group-append>
            <b-btn type="submit" variant="info">Send</b-btn>
          </b-input-group-append>
        </b-input-group>
      </b-form>
    </b-col>
  </b-row>
</template>

<script>

import axios from 'axios'

export default {
  name: 'ChatRoom',
  data () {
    return {
      chats: [],
      errors: [],
      nickname: this.$route.params.nickname,
      chat: {}
    }
  },
  created () {
    axios.get(`http://localhost:3000/api/chat/` + this.$route.params.id)
    .then(response => {
      this.chats = response.data
    })
    .catch(e => {
      this.errors.push(e)
    })
  },
  methods: {
    logout (id) {
      this.$router.push({
        name: 'JoinRoom',
        params: { id: id }
      })
    },
    onSubmit (evt) {
      evt.preventDefault()
      this.chat.room = this.$route.params.id
      this.chat.nickname = this.$route.params.nickname
      axios.post(`http://localhost:3000/api/chat`, this.chat)
      .then(response => {
        // this.$router.push({
        //   name: 'ChatRoom',
        //   params: { id: this.$route.params.id, nickname: response.data.nickname }
        // })
      })
      .catch(e => {
        this.errors.push(e)
      })
    }
  }
}
</script>

<style>
  .chat .left .chat-body {
    text-align: left;
    margin-left: 100px;
  }

  .chat .right .chat-body {
    text-align: right;
    margin-right: 100px;
  }

  .chat .chat-body p {
    margin: 0;
    color: #777777;
  }

  .panel-body {
    overflow-y: scroll;
    height: 350px;
  }

  .chat-form {
    margin: 20px auto;
    width: 80%;
  }
</style>

That code contains the template of the main chat application consist of chat list and sends message form.

12. Integrate Socket.io With Existing Non-Real-time Chat Application

Previous steps show you a regular and non-realtime transaction chat application. Now, we will make it real-time by using Socket.io. First, install socket.io module by type this command.

npm install --save socketio socket.io-client

Next, open and edit routes/chat.js then declare the Socket IO and http module.

var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);

Add this lines of codes for Socket IO functions.

server.listen(4000);

// socket io
io.on('connection', function (socket) {
  console.log('User connected');
  socket.on('disconnect', function() {
    console.log('User disconnected');
  });
  socket.on('save-message', function (data) {
    console.log(data);
    io.emit('new-message', { message: data });
  });
});

In that code, we are running Socket.io to listen for ‘save-message’ that emitted from the client and emit ‘new-message’ to the clients. Next, open and edit src/components/JoinRoom.vue then add this import.

import * as io from 'socket.io-client'

Declare Socket IO variable.

data () {
  return {
    chat: {},
    socket: io('http://localhost:4000')
  }
},

Add Socket IO emit function after successful join room.

axios.post(`http://localhost:3000/api/chat`, this.chat)
.then(response => {
  this.socket.emit('save-message', { room: this.chat.room, nickname: this.chat.nickname, message: 'Join this room', created_date: new Date() });
  this.$router.push({
    name: 'ChatRoom',
    params: { id: this.$route.params.id, nickname: response.data.nickname }
  })
})
.catch(e => {
  this.errors.push(e)
})

Next, open and edit src/components/ChatRoom.vue then add this imports and use as Vue module.

import Vue from 'vue'
import * as io from 'socket.io-client'
import VueChatScroll from 'vue-chat-scroll'
Vue.use(VueChatScroll)

Declare Socket IO variable.

data () {
  return {
    chats: [],
    errors: [],
    nickname: this.$route.params.nickname,
    chat: {},
    socket: io('http://localhost:4000')
  }
},

Add this Socket IO on function to created method.

created () {
  axios.get(`http://localhost:3000/api/chat/` + this.$route.params.id)
  .then(response => {
    this.chats = response.data
  })
  .catch(e => {
    this.errors.push(e)
  })

  this.socket.on('new-message', function (data) {
    if(data.message.room === this.$route.params.id) {
      this.chats.push(data.message)
    }
  }.bind(this))
},

Add Logout function inside methods and add Socket IO emit method in the POST response.

methods: {
  logout () {
    this.socket.emit('save-message', { room: this.chat.room, nickname: this.chat.nickname, message: this.chat.nickname + ' left this room', created_date: new Date() });
    this.$router.push({
      name: 'RoomList'
    })
  },
  onSubmit (evt) {
    evt.preventDefault()
    this.chat.room = this.$route.params.id
    this.chat.nickname = this.$route.params.nickname
    axios.post(`http://localhost:3000/api/chat`, this.chat)
    .then(response => {
      this.socket.emit('save-message', response.data)
      this.chat.message = ''
    })
    .catch(e => {
      this.errors.push(e)
    })
  }
}

Finally, to make Chat list always scroll to the bottom of Chat element add install this module.

npm install --save vue-chat-scroll

That module already imported and declared above. Next, add to the Chat element.

<b-list-group class="panel-body" v-chat-scroll>
  ...
</b-list-group>

13. Run and Test The MEVN (Vue.js 2) Chat Application**

To run this MEVN (Vue.js 2) Chat Application locally, make sure MongoDB service is running. Type this command to build the Vue.js 2 application then run the Express.js application.

npm start

Next, open the different browser (ex: Chrome and Firefox) then go to the localhost:3000 on both of the browsers. You will see this page and you can start Chat.

That it’s, the MongoDB, Express, Vue.js 2, Node.js (MEVN) and SocketIO Chat App. You can find the full working source code on our GitHub.

Thanks!

=============================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ MERN Stack Front To Back: Full Stack React, Redux & Node.js

☞ The Complete Node.js Developer Course (3rd Edition)

☞ Angular & NodeJS - The MEAN Stack Guide

☞ NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

☞ Docker for Node.js Projects From a Docker Captain

☞ Intro To MySQL With Node.js - Learn To Use MySQL with Node!

☞ Node.js Absolute Beginners Guide - Learn Node From Scratch

☞ React Node FullStack - Social Network from Scratch to Deploy

☞ Selenium WebDriver - JavaScript nodeJS webdriver IO & more!

☞ Complete Next.js with React & Node - Beautiful Portfolio App

☞ Build a Blockchain & Cryptocurrency | Full-Stack Edition

Создание сайта на Mongo DB, Express JS, Node JS и Angular

Создание сайта на Mongo DB, Express JS, Node JS и Angular

Видео курс по изучению стека MEAN. В курсе вы научитесь создавать сайты при помощи Node JS, Express JS, Angular JS и баз данных MongoDB. Вы ознакомитесь со всеми моментами разработки и в конце курса выгрузите сайт на удаленный сервер.

Видео курс по изучению стека MEAN. В курсе вы научитесь создавать сайты при помощи Node JS, Express JS, Angular JS и баз данных MongoDB. Вы ознакомитесь со всеми моментами разработки и в конце курса выгрузите сайт на удаленный сервер.