Creating a MEAN Stack SPA with CRUD Operations

Creating a MEAN Stack SPA with CRUD Operations

01 May 2024
Advanced
33.9K Views
17 min read
Learn with an interactive course and practical hands-on labs

Node.js Course

MEAN stack stands for MongoDB, Express, AngularJS and Node.js. MEAN stack is a most popular full-stack JavaScript solution for developing fast, robust and scalable web applications. It uses MongoDB to store data in JSON/BSON formats which makes it well suited to use with JavaScript. It uses Express as Node.js web application framework. It uses AngularJS as front-end SPA development. It uses Node.js as Server Side JavaScript environment.

MEAN stack

#Why MEAN Stack

MEAN stack uses Node.js as javascript server-side environment which is based non-blocking I/O paradigm. Node.js provides more efficiency per CPU core than multi threads languages like C#, Java and Php etc. Also, there are following reasons to use MEAN stack for web development.

  1. One Language

    MEAN stack uses JavaScript as a programming language for both client-side and server-side. Language unification improve the developer productivity.

  2. One Object

    Programmers write code in object oriented fashion and MEAN stack allows you to play with same object on client-side, server-side and also in database-side. So, there is no need to use libraries for converting data into objects during client-side and server-side interaction.

    Why MEAN
  3. NoSQL database

    MEAN stack uses most popular NoSQL database (MongoDB) that is extremely flexible as compared to RDBMS. You don’t need to worry about the schema changes and database migrations.

  4. Cross Platform

    All the technologies used by the MEAN stack are cross platform compatible. They can run on windows, linux, mac etc.

  5. Free and Open Source

    All the technologies used by the MEAN stack are free and open-source. Hence, you need to worry about the cost.

  6. Community Support

    All the technologies used by the MEAN stack have very good community support. You will find a lot of samples for Node.js, Express, AngularJS and MongoDB.

Read More - Node JS Interview Questions and Answers

#MEAN App Structure

A typical folder structure for a MEAN stack application is given below:

MEAN App Structure

#MEAN App Pre-requisite

Here, Node.js and Express will be used to develop backend like running server, configuration settings, and routing. MongoDB will be used to store data in JSON format. AngularJS will be used to develop application front-end part.

To get started with MEAN stack development, you should have the following softwares:

  1. JavaScript Development IDE like Visual Studio Code, WebStorm, Brackets etc.

  2. Node.js

  3. MongoDB

#Setting Up MEAN Stack Application

Here, I am using VS Code for building the app. First of all, create an empty folder called "MEAN_App" in your drive, navigate to this folder and open it with VS Code.Let's inialize MEAN Stack app by running command npm init using VS Code integrated terminal.

> npm init

When you will run above command, it will ask to you some input like project name, version, description etc. Just provides all these inputs and in this way it will create a package.json file within your project folder having following code.

{
 "name": "mean_app",
 "version": "1.0.0",
 "description": "mean app",
 "main": "server.js", 
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "start": "node server.js"
 },
 "keywords": [
 "mean",
 "crud",
 "crud",
 "operations"
 ],
 "author": "shailendra",
 "license": "ISC"
}

#Installing Node Modules

Let's install node modules one by one, like express, body-parser and mongoose for backend code; and angular, angular-ui-router and bootstrap for front-end code. Use save option for adding node modules as production dependencies.

npm install express --save
npm install mongoose --save
npm install angular --save
npm install angular-ui-router --save
npm install bootstrap --save

#The Backend - Node, Express and MongoDB

Let's create backend of our application using Node.js, Express and MongoDB. First of all create server.js file within MEAN_App folder for creating a simple express server and create other folders and files as shown in given fig.

MEAN Folder Structure

Now, write the code for express server as given below:

//========= importing modules ==========
var express = require('express'),
 path = require('path'),
 bodyParser = require('body-parser'),
 routes = require('./server/routes/web'), //web routes
 apiRoutes = require('./server/routes/api'), //api routes
 connection = require("./server/config/db"); //mongodb connection

// creating express server
var app = express();

//========= configuration ==========

//===== get all the data from the body (POST)

// parse application/json 
app.use(bodyParser.json());

// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }));

// setting static files location './app' for angular app html and js
app.use(express.static(path.join(__dirname, 'app')));
// setting static files location './node_modules' for libs like angular, bootstrap
app.use(express.static('node_modules'));

// configure our routes
app.use('/', routes);
app.use('/api', apiRoutes);

// setting port number for running server
var port = process.env.port || 3000;

// starting express server
app.listen(port, function() {
 console.log("Server is running at : http://localhost:" + port);
});

#MongoDB Configuration

To define MongoDB configuration setting, add a db.js file in config folder and add following code to make a connection with MongoDB database.

var mongoose = require('mongoose');
var connection = mongoose.connect('mongodb://localhost/mean_db');

module.exports = connection;

#Mongoose Model

Let's define the MongoDB user document mappings with the help of Mongoose model. The Mongoose model allow us to handle CRUD operations on user document.

Let’s open server/models/user.js file and add the following code:

var mongoose = require("mongoose"),
 Schema = mongoose.Schema,
 objectId = mongoose.Schema.ObjectId;

var userSchema = new Schema({
 _id: { type: objectId, auto: true },
 name: { type: String, required: true },
 contactNo: { type: String, required: true },
 address: { type: String, required: true }
}, {
 versionKey: false
});

var user = mongoose.model('users', userSchema);

module.exports = user;

#Creating User API Controller

Let's define the user api controller to perform CRUD opeartions on MongoDB's user document. Let’s open server/controllers/user.api.js file and add the following code:

var express = require("express"),
 router = express.Router(),
 user = require("../models/user.js");

router.get("/", function(req, res) {
 user.find({}, function(err, data) {
 if (err) {
 res.send("error");
 return;
 }
 res.send(data);
 });
}).get("/:id", function(req, res) {
 var id = req.params.id;
 user.find({ _id: id }, function(err, data) {
 if (err) {
 res.send("error");
 return;
 }
 res.send(data[0]);
 });
}).post("/", function(req, res) {
 var obj = req.body;
 var model = new user(obj);
 model.save(function(err) {
 if (err) {
 res.send("error");
 return;
 }
 res.send("created");
 });
}).put("/:id", function(req, res) {
 var id = req.params.id;
 var obj = req.body;

 user.findByIdAndUpdate(id, { name: obj.name, contactNo: obj.contactNo, address: obj.address }, 
function(err) {
 if (err) {
 res.send("error");
 return;
 }
 res.send("updated");
 });
}).delete("/:id", function(req, res) {
 var id = req.params.id;
 user.findByIdAndRemove(id, function(err) {
 if (err) {
 res.send("error");
 return;
 }
 res.send("deleted");
 });
});

module.exports = router;

#Routes Configuration

Let's configure the routes for our REST API and web (Angular App). Let’s open server/routes/api.js file write the code for configuring routes for our API routes as given below:

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

//routes for user api
router.use("/user", require("../controllers/user.api"));

//add here other api routes

module.exports = router;

Let's configure the routes for our web (Angular App). Let’s open server/routes/web.js file and write the code:

var express = require('express'),
 router = express.Router(),
 path = require("path");

var absPath = path.join(__dirname, "../../app");

// route to handle home page
router.get('/', function(req, res, next) {
 res.sendFile(absPath + "/app.html");
});

module.exports = router;

The Backend Code Done!

In this way, backend code has been done. At this point we should start express server and test our REST API code.

Let's start our MongoDB server by running following command using VS Code integrated terminal.

> mongod

Now, open one more instance of integrated terminal and run the following command to run server.

> node server

#Testing REST API

Let's test our REST API using Google Chrome REST client extensions like Postman, REST Client etc. Here, I am using Postman for testing our REST API.

  1. Create Operation

    Node REST API POST
  2. CREATE Operation

    Node REST API POST
  3. RETRIEVE Operation

    Node REST API GET ALL
    Node REST API GET One
  4. UPDATE Operation

    Node REST API PUT
  5. DELETE Operation

    Node REST API DELETE

#The Frontend - Setting Up AngularJS SPA

Let's create frontend of our application using AngularJS. Let's create folders for AngularJS components like controllers, services and views. Here is the folder structure for AngularJS SPA.

Angular SPA

#App Layout

Let’s create index.html file within MEAN_App/app folder as a layout for Angular SPA.

<!DOCTYPE html>
<html ng-app="app">
<head>
 <meta charset="UTF-8">
 <title>{{Title}}</title>
 <link href="bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
 <script src="angular/angular.js"></script>
 <script src="angular-ui-router/release/angular-ui-router.js"></script>

 <script src="app.js"></script>
 <script src="services/service.js"></script>
 <script src="controllers/user.controller.js"></script>
</head>
<body>
<nav class="navbar navbar-default">
 <div class="container-fluid">
 <div class="navbar-header">
 <a class="navbar-brand" ui-sref="users">MEAN CRUD</a>
 </div>
 <ul class="nav navbar-nav">
 <li><a ui-sref="users">Home</a></li>
 <li><a ui-sref="create">Create</a></li>
 </ul>
 </div>
</nav>

<div class="container">
 <ui-view></ui-view>
</div>
</body>
</html>

#Angular Module and Routes Configuration

Let's configure the routes for our Angular App. Let’s open app/app.js file and write the code for configuring routes for our AngularJS SPA as given below:

(function() {
 'use strict';

 angular.module('app', [
 "ui.router"
 ])
 .config(function($stateProvider, $urlRouterProvider) {
 $urlRouterProvider.otherwise("/");

 $stateProvider.state("users", {
 url: "/",
 templateUrl: "/views/user/index.html",
 controller: "userController"
 }).state("create", {
 url: "/create",
 templateUrl: "/views/user/create.html",
 controller: "userController"
 }).state("edit", {
 url: "/edit/:id",
 templateUrl: "/views/user/create.html",
 controller: "userController"
 }).state("details", {
 url: "/details/:id",
 templateUrl: "/views/user/details.html",
 controller: "userController"
 });
 })
 .constant("globalConfig", {
 apiAddress: 'http://localhost:3000/api'
 });
})();

#Angular Services

Let's create Angular Service named as userService for calling Node.js REST API using Angular $http service as given below:

(function() {
 'use strict';

 angular
 .module('app')
 .factory('userService', Service);

 Service.$inject = ['$http', 'globalConfig'];

 function Service($http, globalConfig) {
 var url = "";
 return {
 getUsers: function() {
 url = globalConfig.apiAddress + "/user";
 return $http.get(url);
 },
 getUser: function(id) {
 url = globalConfig.apiAddress + "/user/" + id;
 return $http.get(url);
 },
 createUser: function(user) {
 url = globalConfig.apiAddress + "/user";
 return $http.post(url, user);
 },
 updateUser: function(user) {
 url = globalConfig.apiAddress + "/user/" + user._id;
 return $http.put(url, user);
 },
 deleteUser: function(id) {
 url = globalConfig.apiAddress + "/user/" + id;
 return $http.delete(url);
 }
 };
 }
})();

#Angular Controllers

Let's create Angular Controller and with the help above created userService perform CRUD operations as given below:

(function() {
 'use strict';

 angular
 .module('app')
 .controller('userController', Controller);

 Controller.$inject = ['$scope', '$rootScope', 'userService', '$state', '$stateParams'];

 function Controller($scope, $rootScope, userService, $state, $stateParams) {
 $scope.users = [];

 if ($state.current.name == "users") {
 $rootScope.Title = "User Listing";
 userService.getUsers().then(function(res) {
 $scope.users = res.data;
 }).catch(function(err) {
 console.log(err);
 });

 $scope.deleteUser = function(id) {
 if (confirm('Are you sure to delete?')) {
 userService.deleteUser(id).then(function(res) {
 if (res.data == "deleted") {
 $state.go("users", {}, { reload: true });
 }
 }).catch(function(err) {
 console.log(err);
 });
 }
 };
 } else if ($state.current.name == "edit") {
 $rootScope.Title = "Edit User";
 var id = $stateParams.id;
 userService.getUser(id).then(function(res) {
 $scope.user = res.data;
 }).catch(function(err) {
 console.log(err);
 });

 $scope.saveData = function(user) {
 if ($scope.userForm.$valid) {
 userService.updateUser(user).then(function(res) {
 if (res.data == "updated") {
 $state.go("users");
 }
 }).catch(function(err) {
 console.log(err);
 });
 }
 };
 } else if ($state.current.name == "create") {
 $rootScope.Title = "Create User";
 $scope.saveData = function(user) {
 $scope.IsSubmit = true;
 if ($scope.userForm.$valid) {
 userService.createUser(user).then(function(res) {
 if (res.data == "created") {
 $state.go("users");
 }
 }).catch(function(err) {
 console.log(err);
 });
 }
 };
 }
 }
})();

#Angular Views

Let's create Angular views for CRUD operations as given below:

<-- Create.html -->
<h2 ng-show="user._id!=null">Edit</h2>
<h2 ng-hide="user._id!=null">Create</h2>
<hr>
<form name="userForm" ng-submit="saveData(user)" novalidate class="form-horizontal">
 <div class="form-group">
 <label class="col-md-2">Name</label>
 <div class="col-md-10">
 <input type="text" ng-model="user.name" name="name" ng-required="true" class="form-control"/>
 <p ng-show="userForm.name.$error.required && (userForm.$submitted || userForm.name.$dirty)" class="text-danger">Please Enter Name</p>
 </div>
 </div>
 <div class="form-group">
 <label class="col-md-2">Address</label>
 <div class="col-md-10">
 <textarea name="address" ng-model="user.address" ng-required="true" class="form-control"></textarea>
 <p ng-show="userForm.address.$error.required && (userForm.$submitted || userForm.address.$dirty)" class="text-danger">Please Enter Address</p>
 </div>
 </div>
 <div class="form-group">
 <label class="col-md-2">Contact No.</label>
 <div class="col-md-10">
 <input type="text" ng-model="user.contactNo" name="contactNo" ng-required="true" class="form-control"/>
 <p ng-show="userForm.contactNo.$error.required && (userForm.$submitted || userForm.contactNo.$dirty)" class="text-danger">Please Enter Contact No.</p>
 </div>
 </div>
 <div class="form-group">
 <div class="col-md-offset-2 col-md-10">
 <input type="submit" value="Update" class="btn btn-primary" ng-show="user._id!=null"/>
 <input type="submit" value="Save" class="btn btn-primary" ng-hide="user._id!=null"/>
 <a ui-sref="users" class="btn btn-warning">Cancel</a>
 </div>
 </div>
</form>
<-- index.html -->
<h2>Users Listing</h2>

<table class="table" ng-if="users.length>0">
 <tr>
 <th>SNo.</th>
 <th>Name</th>
 <th>Address</th>
 <th>Contact No.</th>
 <th>Actions</th>
 </tr>
 <tr ng-repeat="user in users">
 <td>{{$index+1}}</td>
 <td>{{user.name}}</td>
 <td>{{user.address}}</td>
 <td>{{user.contactNo}}</td>
 <td>
 <a ui-sref="edit({id:user._id})">Edit</a> |
 <a href="#" ng-click="deleteUser(user._id)">Delete</a>
 </td>
 </tr>
</table>
<div ng-if="users.length==0">
 No record found !!
</div>

The Frontend Code Done!

In this way, frontend code has been done. At this point we should start mongodb and express server and test our MEAN app.

Create Operation

Angular SPA Post

Reterieve Operation

Angular SPA Get

Update Operation

Angular SPA Put

Delete Operation

Angular SPA Delete
What do you think?

Now you have a complete MEAN stack application having Node.js, Express, and MonogoDB as backend and AngularJS as frontend. You should use MEAN stack to build fast, robust and scalable web applications using JavaScript as a primary language. You can refer this article to develop any MEAN stack application. I would like to have feedback from my blog readers. Your valuable feedback, question, or comments about this article are always welcome.

Take our Nodejs skill challenge to evaluate yourself!

In less than 5 minutes, with our skill challenge, you can identify your knowledge gaps and strengths in a given skill.

GET FREE CHALLENGE

Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

Shailendra Chauhan is the Founder and CEO at ScholarHat by DotNetTricks which is a brand when it comes to e-Learning. He provides training and consultation over an array of technologies like Cloud, .NET, Angular, React, Node, Microservices, Containers and Mobile Apps development. He has been awarded Microsoft MVP 9th time in a row (2016-2024). He has changed many lives with his writings and unique training programs. He has a number of most sought-after books to his name which has helped job aspirants in cracking tough interviews with ease.
Accept cookies & close this