AngularJS example MotoAds with NodeJS and MongoDB
I built MotoAds demo application in AngularJS but it did not have any server layer. Data was read directly from the json files. So I was decided to build the server side services. I know pretty well JEE and relational database, so I could use it. But I want to know something new so I chose NodeJS nad MongoDB. Thanks to this decision I got a full stack JavaScript application. It's incredible to use JavaScript to build the complete application.
Now MotoAds demo application consists of:
Step 1
We write in
Step 2
Inject services in
We use the angularjs services in
Step 3
In
Step 4
In
We run MongoDB and start our HTTP server (
If you want to run this example on your computer, you can download sources from GitHub.
Any comment would be highly appreciated.
- User interface in AngularJS and Bootstrap with full CRUD operations: add, read, edit and remove adverts.
- Server service layer was built in NodeJS with RESTful serrvices. To simplify the use of a NodeJS I used ExpressJS.
- Database: all data except the pictures are stored in MongoDB.
Step 1
We write in
services.js
access to our RESTful services:
'use strict'; var motoAdsServices = angular.module('motoAdsServices', ['ngResource']); motoAdsServices.factory('Brand', ['$resource', function($resource) { return $resource('/api/brands', {}, {}); }]); motoAdsServices.factory('Country', ['$resource', function($resource) { return $resource('/api/countries', {}, {}); }]); motoAdsServices.factory('Advert', ['$resource', function($resource) { return $resource('/api/adverts/:advertId', {}, { update: {method:'PUT', params: {advertId: '@_id'}} }); }]);
Step 2
Inject services in
app.js
:
'use strict'; var motoAdsApp = angular.module('motoAdsApp', ['ngRoute', 'ui.bootstrap', 'motoAdsServices']); motoAdsApp.config(['$routeProvider', function($routeProvider) { $routeProvider. when('/', { controller: 'AdvertsController', templateUrl: 'views/adverts.html' }). when('/addAdvert', { controller: 'AddAdvertController', templateUrl: 'views/addAdvert.html' }). when('/editAdvert/:advertId', { controller: 'EditAdvertController', templateUrl: 'views/editAdvert.html' }); }]);
We use the angularjs services in
controllers.js
:
motoAdsApp.controller('AdvertsController', ['$scope', '$window', 'Brand', 'Country', 'Advert', function($scope, $window, Brand, Country, Advert) { // ... $scope.brands = Brand.query(); $scope.countries = Country.query(); // ... $scope.adverts = []; var allAdverts = Advert.query(filterAdverts); // ... $scope.$watch('filter', filterAdverts, true); function filterAdverts() { $scope.adverts = []; angular.forEach(allAdverts, function(row) { // ... $scope.adverts.push(row); }); } $scope.removeAdvert = function(idx) { var removeAdvert = $scope.adverts[idx]; Advert.remove({advertId: removeAdvert._id}, function() { $scope.adverts.splice(idx, 1); alert('Advert removed'); }); }; $scope.editAdvert = function(_advertId) { $window.location = "#/editAdvert/" + _advertId; }; }]); motoAdsApp.controller('AddAdvertController', ['$scope', '$window', 'Brand', 'Country', 'Advert', function($scope, $window, Brand, Country, Advert) { $scope.brands = Brand.query(); $scope.countries = Country.query(); // ... $scope.addAdvert = function() { Advert.save($scope.newAdvert, function() { alert('New advert added'); $window.location = "#/"; }); }; // ... }]); motoAdsApp.controller('EditAdvertController', ['$scope', '$routeParams', '$window', 'Brand', 'Country', 'Advert', function($scope, $routeParams, $window, Brand, Country, Advert) { $scope.brands = Brand.query(); //... $scope.countries = Country.query(); // ... var previousAdvert = null; $scope.editAdvert = Advert.get({advertId: $routeParams.advertId}, function() { // ... }); $scope.updateAdvert = function() { Advert.update($scope.editAdvert, function() { alert('Advert updated'); $window.location = "#/"; }); }; // ... }]);
Step 3
In
server.js
we create the HTTP server with the RESTful service in NodeJS and ExpressJS. It is also used to host angularjs app:
var express = require('express'); var path = require('path'); var http = require('http'); var brands = require('./routes/brands'); var countries = require('./routes/countries'); var adverts = require('./routes/adverts'); var app = express(); app.configure(function() { app.set('port', process.env.PORT || 3000); app.use(express.logger('dev')); /* 'default', 'short', 'tiny', 'dev' */ app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(express.static(path.join(__dirname, 'public'))); // TODO should be created separate test server app.use('/test', express.static(path.join(__dirname, 'test'))); }); app.get('/api/brands', brands.findAll); app.get('/api/countries', countries.findAll); app.get('/api/adverts', adverts.findAll); app.get('/api/adverts/:id', adverts.findById); app.post('/api/adverts', adverts.add); app.put('/api/adverts/:id', adverts.update); app.delete('/api/adverts/:id', adverts.remove); http.createServer(app).listen(app.get('port'), function() { console.log("Express server listening on port " + app.get('port')); });
Step 4
In
adverts.js
we write some code in NodeJS which allows us to use MongoDB:
var mongo = require('mongodb'); var Server = mongo.Server; var Db = mongo.Db; var BSON = mongo.BSONPure; var server = new Server('localhost', 27017, {auto_reconnect: true}); db = new Db('motoads', server); db.open(function(err, db) { if (!err) { console.log("Connected to motoads database"); db.collection('adverts', {strict: true}, function(err, collection) { if (err) { console.log("The adverts collection does not exist. Creating it with sample data..."); populateDB(); } }); } }); exports.findAll = function(req, res) { db.collection('adverts', function(err, collection) { collection.find().toArray(function(err, items) { console.log('adverts send from DB'); res.send(items); }); }); }; exports.findById = function(req, res) { var id = req.params.id; console.log('Retrieving advert: ' + id); db.collection('adverts', function(err, collection) { collection.findOne({'_id': new BSON.ObjectID(id)}, function(err, item) { res.send(item); }); }); }; exports.add = function(req, res) { var advert = req.body; console.log('Adding advert: ' + JSON.stringify(advert)); db.collection('adverts', function(err, collection) { collection.insert(advert, {safe: true}, function(err, result) { if (err) { res.send({'error': 'An error has occurred'}); } else { console.log('Success: ' + JSON.stringify(result[0])); res.send(result[0]); } }); }); }; exports.update = function(req, res) { var id = req.params.id; var advert = req.body; console.log('Updating advert: ' + id); console.log(JSON.stringify(advert)); delete advert._id; db.collection('adverts', function(err, collection) { collection.update({'_id': new BSON.ObjectID(id)}, advert, {safe: true}, function(err, result) { if (err) { console.log('Error updating advert: ' + err); res.send({'error': 'An error has occurred'}); } else { console.log('' + result + ' document(s) updated'); res.send(advert); } }); }); }; exports.remove = function(req, res) { var id = req.params.id; console.log('Removing advert: ' + id); db.collection('adverts', function(err, collection) { collection.remove({'_id': new BSON.ObjectID(id)}, {safe: true}, function(err, result) { if (err) { res.send({'error': 'An error has occurred - ' + err}); } else { console.log('' + result + ' document(s) removed'); res.send(req.body); } }); }); }; var populateDB = function() { var fs = require('fs'); var file = './data/adverts.json'; fs.readFile(file, 'utf8', function(err, data) { if (err) { throw err; } var adverts = JSON.parse(data); db.collection('adverts', function(err, collection) { if (err) { throw err; } collection.insert(adverts, {safe: true}, function(err, result) { if (err) { throw err; } }); }); }); };
We run MongoDB and start our HTTP server (
node server.js
). Now we are typing in web browser URL http://localhost:3000/#/
. In web browser we should see the MotoAds application and we can use CRUD operations.
If you want to run this example on your computer, you can download sources from GitHub.
Any comment would be highly appreciated.
Komentarze