Develop MEAN Stack Application

“MEAN” stack is an open source JavaScript stack for building dynamic web applications. It’s an acronym for MongoDB, Express.js, Angular and Node.js.

In this article, I am going to explain about developing a MEAN stack application from the scratch. I assume that the reader should have a basic understanding of JavaScript. If not,  Please familiarize yourself with Javascript.

Setup

The first step is to install the MongoDB, Express.js, and Node.js in your system/laptop.

I assume that you are using Windows. If you use Ubuntu or Linux, then follow the necessary steps to install the MongoDB and Node.js

MongoDB:

  1. Go to https://www.mongodb.com/download-center#community and download the installation package.
  2. Run the installer file and complete the installation.  By default, it’s getting installed in C:\Program Files\MongoDB.
  3. Create /data/db to store the data.
  4. To start the MongoDB server, go to C:\Program Files\MongoDB\bin,  then run mongod.exe. By default, it’s running on 27017.
  5. We can run the MongoDB client by running “mongo.exe” and type “show dbs” to list out the default database name.

Node.Js:

  1. Go to https://nodejs.org/en/download and download the windows installer.
  2. Run the installer file and finish the installation.
  3. Open up Node.js command prompt, then verify the node and npm version(node -v and npm -v) to validate the installation.

Express.js

Open up Node.js command prompt and run the below command to install Express.js.

 npm install -g express

That’s it.  We are done with the environment setup. Let’s move on to the application.

Application Flow

It’s a simple application for adding, viewing and deleting the user comments. While loading the home page, it will access the MongoDB and get the list of Comments. It also allows to add and delete the comments.

The directory structure is given below,

Directory Structure

Start it from the “server.js”. This is the starting point of the application. In this file, we do the setup, database and routes configuration and finally starting the Node.js server. I have provided the enough comments in the below code section to help for more understanding.

server.js


// server.js

// Modules ===============================================================
var express = require('express');
//Create the application with express
var app = express();
//mongoose is for  mongodb
var mongoose = require('mongoose');
// log requests to the console
var morgan = require('morgan');
// pull information from HTML POST
var bodyParser = require('body-parser');
// simulate DELETE and PUT
var methodOverride = require('method-override');

// Configuration ===============================================================
var database = require('./config/database');
//Connect to mongoDB
mongoose.connect(database.url);
// Set the port
var port = 8081;

// set the static files location /public/img will be /img for users

app.use(express.static(__dirname + '/public'));
// log every request to the console
app.use(morgan('dev'));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({'extended': 'true'}));
// parse application/json
app.use(bodyParser.json());
// parse application/vnd.api+json as json
app.use(bodyParser.json({type: 'application/vnd.api+json'}));

app.use(methodOverride());

// Routes ======================================================================
// configure our routes
require('./app/routes.js')(app);

// startup our app at http://localhost:8081
app.listen(port);
console.log("App listening on port : " + port);

Now let’s see the database configuration,  Refer the file /config/database.js


// config/database.js
module.exports = {
    url : 'mongodb://localhost/'
 };

Back End(Node.js)

Now let’s refer the routes.js where we define the REST services. We have three REST services, They are /api/comments/fetchAll, /api/comments/save and /api/comments/delete/:comment_id. So with the name itself, you can understand the purpose of each service.

Before going to this service, We have to create an object model with mongoose which is an object modeling tool designed to work in an asynchronous environment.

Refer the app/models/comment.js. Here I am creating a model object with userName and comment field.

comment.js


//app/models/comment.js

// load mongoose to define the model
var mongoose = require('mongoose');

module.exports = mongoose.model('Comment', {
    userName : String,
    comment : String,
    done : Boolean
});

Now refer the routes.js. The first step is to load the ‘Comment’ model and then use this model for adding, viewing and deleting the comments. I have provided enough comments in the code section itself. Hence go through it.

routes.js


// app/routes.js
// load the Comment model
var Comment = require('./models/comment');

// expose the routes to our app with module.exports
module.exports = function(app) {

    // get all comments
    app.get('/api/comments/fetchAll', function(req, res) {

        // use mongoose to get all comments in the database
        Comment.find(function(err, comments) {

            // if there is an error retrieving, send the error. nothing after res.send(err) will execute
            if (err)
                res.send(err);

            res.json(comments); // return all comments in JSON format
        });
    });

    // create comment and send back all comments after creation
    app.post('/api/comments/save', function(req, res) {

        // create a Comment, information comes from AJAX request from Angular
        Comment.create({
            comment: req.body.comment,
            userName: req.body.userName,
            done: false
        }, function(err, comment) {
            if (err)
                res.send(err);

            // get and return all the comments after you create another
            Comment.find(function(err, comments) {
                if (err)
                    res.send(err);
                res.json(comments);
            });
        });

    });

    // delete a Comment and send back all remaining Comments
    app.delete('/api/comments/delete/:comment_id', function(req, res) {
        Comment.remove({
            _id: req.params.comment_id
        }, function(err, todo) {
            if (err)
                res.send(err);

            // get and return all the comments after the delete operation to make sure that the comment got deleted
            Comment.find(function(err, comments) {
                if (err)
                    res.send(err);
                res.json(comments);
            });
        });
    });
};

We are done with the back end. Let’s move on to the Angular Front End code to know how these services are being used.

Front End(Angular)

The index.html and core.js are the core components of front-end layer.

The core.js contains the angular controller code to access the REST services and populate the ‘formdata’. Here we create the Angular Module ‘commentModule’ and assign the ‘commentController’ to this.  This controller is responsible for loading the comments while loading the home page, creating the comments and finally removing it.

core.js


// public/core.js
var commentApp = angular.module('commentModule', []);

commentApp.controller('commentController', ['$scope', '$http', function ($scope, $http) {

    $scope.formData = {};

    // when landing on the page, get all comments and show them
    $http({
        method: 'GET',
        url: '/api/comments/fetchAll'
    }).then(function success(response) {
        console.log(response.data);
        $scope.comments = response.data;
    }, function error(response) {
        console.log('Error: ' + response.data);
    });

    // when submitting the add form, send the text to the node API
    $scope.createComment = function () {
        var userName = $scope.formData.userName;
        var comment = $scope.formData.comment;

        if (userName != null && comment != null && userName.trim().length != 0 && comment.trim().length != 0) {
            $http({
                method: 'POST',
                data: $scope.formData,
                url: '/api/comments/save'
            }).then(function success(response) {
                $scope.formData = {}; // clear the form so our user is ready to enter another
                $scope.comments = response.data;
                console.log(response.data);
            }, function error(response) {
                console.log('Error: ' + response.data);
            });
        } else {
            alert("Either UserName or Comment is empty")
        }
    };

    // delete a comment after checking it
    $scope.deleteComment = function (id) {
        $http({
            method: 'DELETE',
            url: '/api/comments/delete/' + id
        }).then(function success(response) {
            console.log(response.data);
            $scope.comments = response.data;
        }, function error(response) {
            console.log('Error: ' + response.data);
        });
    };
}]);

index.html

We have to refer the ‘commentModule’ and ‘commentController’ from the index.html. So the ng-app directive refers the ‘commentModule’ and the ng-controller refers  ‘commentController’ respectively. Next, we have User Name and comment fields and check the ng-model for these fields and its getting mapped to formData.userName and formData.comment respectively. We use the ng-repeat directive to show the list of comments. While clicking on ‘Add’ button will call createComment() function which in turn call the REST (/api/comments/save) service and save the new comments on MongoDB. There is a checkbox which will be shown for each comment. If you click on given checkbox, it will call deleteComment() function which will delete that comment from MongoDB.

<html ng-app="commentModule">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>MEAN Stack Comments Application</title>

    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <!-- load bootstrap -->
    <style>
        html {
            overflow-y: scroll;
        }

        body {
            padding-top: 50px;
        }
    </style>

    <script src="//ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
    <!-- load jquery -->
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
    <!-- load angular -->
    <script src="core.js"></script>

</head>
<!-- Set the controller and get all the comments -->
<body ng-controller="commentController">
<div class="container">

    <div class="jumbotron text-center">
        <h1>Comments List <span class="label label-info">{{ comments.length }}</span></h1>
    </div>

    <div id="comment-list" class="row">
        <div class="col-sm-4 col-sm-offset-4">

            <div class="checkbox" ng-repeat="comment in comments">
                <label>
                    <input type="checkbox" ng-click="deleteComment(comment._id)"> <b>{{ comment.userName }} </b> : {{
                    comment.comment }}
                </label>
            </div>

        </div>
    </div>
    <!-- FORM TO Enter Comments -->
    <div id="comment-form" class="row">
        <div class="col-sm-8 col-sm-offset-2 text-center">
            <form>
                <div class="form-group">
                    <table>
                        <tr>
                            <td><b>User Name:</b></td>
                            <td><input type="text" class="form-control input-lg text-center" placeholder="User Name" ng-model="formData.userName"></td>
                        </tr>
                        <tr>
                            <td><b>Comments:</b></td>
                            <td><textarea rows="4" cols="40" class="form-control input-lg text-center" placeholder="Comments"
                                          ng-model="formData.comment"> </textarea></td>
                        </tr>
                    </table>
                </div>
                <!-- createComments() WILL CREATE NEW Comments -->
                <button type="submit" class="btn btn-primary btn-lg" ng-click="createComment()">Add</button>
            </form>
        </div>
    </div>
</div>
</body>
</html>

Now it’s time to run the application. Follow the below steps to do that.

  1. Check out the project from https://github.com/dkbalachandar/meanstack-comments-application
  2. Type ‘npm install’ to install all the required modules.
  3. Type ‘npm start server.js’ to run it.
  4. If you would like to run this as a daemon process, then do below,
    Install forever by running ” npm install -g forever”
    Start the server by running “forever start server.js”
    Stop the server by running “forever stop server.js”
  5. Open up the browser and type http://localhost:8081

Refer below the screenshots taken.

Home Page

Home Page

Try to add few comments

After adding  few Comments, the top section shows the number of comments and the actual comments entered

After adding few comments

 

 

Remove the first comment by clicking on the checkbox, so the first comment will be removed and the remaining comments will be shown as below.

After Deleting First Comment

 Summary:

In this post, I have explained about developing a MEAN stack application with an example. You can use this project as a base and update the code with creating some more services, then changing the front end code and test it out.

Let me know if you have any questions.

By | 2017-07-22T17:33:49+00:00 January 3rd, 2017|Angular, JavaScript, Mongo DB|0 Comments

About the Author:

Leave A Comment