Vous êtes sur la page 1sur 8

Creating REST API using NodeJS and consuming in AngularJS

angularcode.com/creating-rest-api-using-nodejs-and-consuming-in-angularjs/

16/11/2015

In most of the applications we need to talk to some kind of database. While AngularJS is a client side library which is
capable only at the client side or at browser, now to connect to our database which usually resides at our server we
need NodeJS.

NodeJS is an awesome light weight, non-blocking platform to have at your server which is perfect for data-intensive
real-time applications.

We will create a simple inventory manager app which will communicate to database

Live Demo Download

Database: products-demo
Collection: products
Fields: SKU, Product Name, Price

Our learning path will be like following

Install NodeJS and MongoDB


Create and congure web server to communicate to database (NodeJS + Express)
Craft the client side app (AngularJS)

Install NodeJS, NPM and MongoDB

NodeJs: https://nodejs.org/en/

MongoDB: https://www.mongodb.org/

1/8
Create ReST API

To create a NodeJS application we rst need to create 2 les named:


1. package.json (Denes the architecture and dependency of the nodejs app)

1 {
2 'name': 'ReST API',
3 'version': '1.0.0',
4 'description': 'A simple RESTFul API craeted using nodejs that talk to Mongodb database',
5 'main': 'index.js',
6 'author': 'codenx',
7 'license': 'ISC',
8 'dependencies': {
9 'body-parser': '^1.9.0',
10 'express': '^4.12.4',
11 'mongoose': '^4.0.5',
12 'node-restful': '^0.1.17'
13 }
14 }

2. server.js (This will create a basic webserver similar to Apache)

2/8
1 // Dependencies
2 var express = require('express');
3 var mongoose = require('mongoose');
4 var bodyParser = require('body-parser');
5
6 // MongoDB
7
8 mongoose.connect(process.env.OPENSHIFT_MONGODB_DB_URL || 'mongodb://localhost/products-
9 demo');
10 // mongoose.connection.on('error', function(){});
11
12 // Express
13 var app = express();
14
15 app.use(express.static(__dirname + '/public'));
16
17 app.use(bodyParser.json());
18 app.use(bodyParser.urlencoded({ extended: true }));
19
20 // Routes
21 app.use('/api', require('./routes/api'));
22
23 // Start server
24 var port = process.env.OPENSHIFT_NODEJS_PORT || 8080
25 , ip = process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1";
26 app.listen(port, ip, function() {
27 console.log('Express server listening on %d', port);
});

Now we created our server, lets open command line and navigate to the project folder (C:\nodejs\products)
Enter the following commands

1 npm install
2 node server

npm install Install all required modules dened in package.json le

body-parser Required to parse the JSON data from the client


express Webserver similar to Apache
mongoose Handy module to talk to MongoDB database
node-restful This module automatically create REST API from specied model

node server Run our NodeJS app


3/8
At this point we should see the message Server is running on port 3000
Create the following 2 les

models/product.js Dene the database schema

1 // Dependencies
2 var restful = require('node-restful');
3 var mongoose = restful.mongoose;
4
5 // Schema
6 var productSchema = new mongoose.Schema({
7 name: String,
8 sku: String,
9 price: Number
10 });
11
12 // Return model
13 module.exports = restful.model('Products', productSchema);

routes/api.js Denes the API routes (data providers)

e.g. http://localhost:3000/api/products (get,post,put,delete)


e.g. http://localhost:3000/api/categories (get,post,put,delete)

1 // Dependencies
2 var express = require('express');
3 var router = express.Router();
4
5 //Product
6 var Product = require('../models/product');
7 Product.methods(['get', 'put', 'post', 'delete']);
8 Product.register(router, '/products');
9
10 // Return router
11 module.exports = router;

Now that our API is ready. You can test it using Chrome Postman extension

The next step is to create our client using AngularJS


To call our ReST API we need the help of angular-resource which will make our task easy and fun.
In this application Ive added some animations too.
For this application we will create a factory named Product to interact with our ReST API which in turn interacts
with our database.
We will call this factory from products.js le with dierent methods like get, post, put, delete.
The le public/index.html is the starting point of our application. From here everything starts. This page renders the
view.

4/8
1 ng-app="myApp">
2 Simple demonstration of AngularJS with ReSTful API - AngularCode
3 rel="stylesheet" href="css/bootstrap.min.css">
4 rel="stylesheet" href="css/ngProgress.css">
5 rel="stylesheet" href="css/toaster.css">
6 [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
7 display: none !important;
8 }
9 ng-cloak>
10 class="container" ng-controller="ProductsCtrl">
11 name="Codenx" novalidate>
12 class="table">
13
14
15 Name
16 SKU
17 Price
18 Action
19
20
21
22
23
24 class="form-control" ng-model="product.name" required="" placeholder="Product Name">
25 class="form-control" ng-model="product.sku" placeholder="Stock Control Unit">
26 class="form-control" ng-model="product.price" placeholder="Should be a number">
27 class="btn btn-primary" ng-click="add(product)" ng-if="!product._id" type="submit" ng-
28 disabled="!Codenx.$valid">Add Product
29 class="btn-group">
30 class="btn btn-info" ng-click="update(product)" ng-if="product._id" type="submit">Update
31 class="btn" ng-click="deselect()" ng-if="product._id">Clear
32
33
34
35 ng-repeat="product in products">
36 {{product.name}}
37 {{product.sku}}
38 {{product.price}}
39
40 class="btn-group">
41 class="btn btn-danger" ng-click="remove(product)">Remove
42 class="btn btn-warning" ng-click="edit(product._id)">Edit
43
5/8
44
45
46
47
48
49
50
51
52 data-loading>
53 toaster-options="{'time-out': 3000, 'close-button':true, 'animation-class': 'toast-top-center'}">
54
55 src="js/angular.min.js">
56 src="js/angular-resource.min.js">
57 src="js/angular-animate.min.js">
58 src="js/ngProgress.min.js">
59 src="js/toaster.js">
60 src="app/app.js">
61 src="app/products.js">
62
63
64
65
66
67

We have 2 controller where we dene the business logic and the angular app resides here

app/app.js

1 var app = angular.module('myApp', ['ngResource', 'ngProgress', 'ngAnimate', 'toaster']);


2 app.cong(function ($httpProvider) {
3 $httpProvider.interceptors.push('myHttpInterceptor');
4 });
5
6 // Handle http server errors
7 app.factory('myHttpInterceptor', function ($q,toaster) {
8 return {
9 responseError: function (response) {
10 console.log(response);
11 if(response.data){
12 if(response.data.message)
13 toaster.error("Error: ", response.data.message);
14 else
15 toaster.error("Error: ", response.data);
16 }
6/8
17 return $q.reject(response);
18 }
19 };
20 });
21
22 // Showing loading indicator on top while data is requested from database
23 app.directive('loading', ['$http', 'ngProgress', function ($http, ngProgress)
24 {
25 return {
26 restrict: 'A',
27 link: function (scope, elm, attrs)
28 {
29 scope.isLoading = function () {
30 return $http.pendingRequests.length > 0;
31 };
32
33 scope.$watch(scope.isLoading, function (v)
34 {
35 if(v){
36 ngProgress.start();
37 }else{
38 ngProgress.complete();
39 }
40 });
41 }
42 };
43 }]);
44
45 // Create a resource factory to access products table from database
46 app.factory('Product', function($resource) {
47 return $resource('/api/products/:id', { id: '@_id' }, {
48 update: { // We need to dene this method manually as it is not provided with ng-resource
49 method: 'PUT'
50 }
51 });
52 });

app/products.js

This is the ProductsCtrl where we handle all user interactivity

7/8
1 app.controller('ProductsCtrl', function($scope, Product, ngProgress, toaster) {
2
3 $scope.product = new Product();
4
5 var refresh = function() {
6 $scope.products = Product.query();
7 $scope.product ="";
8 }
9 refresh();
10
11 $scope.add = function(product) {
12 Product.save(product,function(product){
13 refresh();
14 });
15 };
16
17 $scope.update = function(product) {
18 product.$update(function(){
19 refresh();
20 });
21 };
22
23 $scope.remove = function(product) {
24 product.$delete(function(){
25 refresh();
26 });
27 };
28
29 $scope.edit = function(id) {
30 $scope.product = Product.get({ id: id });
31 };
32
33 $scope.deselect = function() {
34 $scope.product = "";
35 }
36
37 })

8/8