Advertisement
  1. Code
  2. JavaScript
  3. Angular

Build an AngularJS App From Scratch, Powered by Python EVE

Scroll to top
Read Time: 12 min

In the previous part of this series, we saw how to get started with Eve, a Python REST API framework, and create some APIs. In this part of the series, we'll make use of those APIs to create an application powered by Node.js and AngularJS.

We'll be implementing the sign-up functionality using Node.js, and adding other functionalities by calling the REST APIs from AngularJS. 

Getting Started

To get started, clone the source code of the previous tutorial and run the APIs.

1
git clone https://github.com/jay3dec/REST_API_EVE_Part-1

Once you have cloned the source code, make sure you have MongoDB running. Navigate to the REST_API_EVE_Part-1 directory and run the app:

1
cd REST_API_EVE_Part-1
2
python app.py

Now, you should have your API running on http://localhost:5000/.

Creating the NodeJS App

Step 1: Creating the Basic App

Create a project folder called AngularNodeApp. We'll be using Express, a minimalistic web application framework for creating Node.js applications. So let's install express into our project.

1
npm install express

Once express has been installed, create a file called app.js. Inside app.js we'll create our express application and define the routes for the application. 

Let's start by importing express into app.js and creating an express app.

1
var express = require('express'),
2
    app = express();
3
4
app.get('/',function(req,res){
5
    res.send('welcome !!');
6
});
7
8
app.listen(3000)

We just created an express app and defined a route, /, which will return welcome when requested. Start the server.

1
node app.js

Point your browser to http://localhost:3000/ and you should have the message welcome !!.

Let's create a home page for our application. Navigate to the project folder and create a new directory called public. Inside public/index create a file called index.html. Add the following HTML code to index.html.

1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
    <title>Angular Node App</title>
6
7
8
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
9
10
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
11
12
13
</head>
14
15
<body>
16
17
    <div class="container">
18
        <div class="header">
19
            <nav>
20
                <ul class="nav nav-pills pull-right">
21
                    <li role="presentation" class="active"><a href="#">Home</a>
22
                    </li>
23
                    <li role="presentation"><a href="/signIn">Sign In</a>
24
                    </li>
25
                    <li role="presentation"><a href="/signUp">Sign Up</a>
26
                    </li>
27
                </ul>
28
            </nav>
29
            <h3 class="text-muted">Angular Node App</h3>
30
        </div>
31
32
        <div class="jumbotron">
33
            <h1>Angular Node App</h1>
34
            <p class="lead"></p>
35
            <p><a class="btn btn-lg btn-success" href="/signUp" role="button">Sign up today</a>
36
            </p>
37
        </div>
38
39
40
41
        <footer class="footer">
42
            <p>&copy; Company 2015</p>
43
        </footer>
44
45
    </div>
46
</body>
47
48
</html>

Next, let's modify the existing / request handler to show index.html. Define the path to the public folder in app.js.

1
app.use(express.static(__dirname + '/public'));

Modify the / request handler as shown:

1
app.get('/',function(req,res){
2
    res.sendFile('index.html',{'root': __dirname + '/public/index'});
3
});

Save the changes and restart the server. Point your browser to http://localhost:3000/ and you should be able to see the application page.

Home PageHome PageHome Page

Next create a page called signin/signin.html and add the following HTML code:

1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
    <title>Python Flask Bucket List App</title>
6
7
8
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
9
10
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
11
    <link href="signup.css" rel="stylesheet">
12
13
14
</head>
15
16
<body>
17
18
    <div class="container">
19
        <div class="header">
20
            <nav>
21
                <ul class="nav nav-pills pull-right">
22
                    <li role="presentation"><a href="/">Home</a>
23
                    </li>
24
                    <li role="presentation" class="active"><a href="#">Sign In</a>
25
                    </li>
26
                    <li role="presentation"><a href="/signUp">Sign Up</a>
27
                    </li>
28
                </ul>
29
            </nav>
30
            <h3 class="text-muted">Python Flask App</h3>
31
        </div>
32
33
        <div class="jumbotron">
34
            <h1>Bucket List App</h1>
35
            <form class="form-signin">
36
                <label for="inputEmail" class="sr-only">Email address</label>
37
                <input type="email" name="inputEmail" id="inputEmail" class="form-control" placeholder="Email address" required autofocus>
38
                <label for="inputPassword" class="sr-only">Password</label>
39
                <input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required>
40
41
                <button id="btnSignIn" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
42
            </form>
43
        </div>
44
45
46
47
        <footer class="footer">
48
            <p>&copy; Company 2015</p>
49
        </footer>
50
51
    </div>
52
</body>
53
54
</html>

In app.js add a request handler called /SignIn which will render the signin.html page.

1
app.get('/signIn', function(req, res) {
2
    res.sendFile('signin.html', {
3
        'root': __dirname + '/public/signin'
4
    });
5
});

Similarly, add a signup.html to the public/signup folder with the following HTML code:

1
<!DOCTYPE html>
2
<html lang="en">
3
4
<head>
5
    <title>Python Flask Bucket List App</title>
6
7
8
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
9
10
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
11
    <link href="signup.css" rel="stylesheet">
12
13
14
</head>
15
16
<body>
17
18
    <div class="container">
19
        <div class="header">
20
            <nav>
21
                <ul class="nav nav-pills pull-right">
22
                    <li role="presentation"><a href="/">Home</a>
23
                    </li>
24
                    <li role="presentation"><a href="/signIn">Sign In</a>
25
                    </li>
26
                    <li role="presentation" class="active"><a href="#">Sign Up</a>
27
                    </li>
28
                </ul>
29
            </nav>
30
            <h3 class="text-muted">Python Flask App</h3>
31
        </div>
32
33
        <div class="jumbotron">
34
            <h1>Bucket List App</h1>
35
            <form class="form-signin" action="/register" method="post">
36
                <label for="inputFirstName" class="sr-only">First Name</label>
37
                <input type="name" name="inputFirstName" id="inputFirstName" class="form-control" placeholder="First Name" required autofocus>
38
                <label for="inputLastName" class="sr-only">Last Name</label>
39
                <input type="name" name="inputLastName" id="inputLastName" class="form-control" placeholder="Last Name" required autofocus>
40
                <label for="inputUsername" class="sr-only">Username</label>
41
                <input type="name" name="inputUsername" id="inputUsername" class="form-control" placeholder="Username" required autofocus>
42
                <label for="inputPassword" class="sr-only">Password</label>
43
                <input type="password" name="inputPassword" id="inputPassword" class="form-control" placeholder="Password" required>
44
                <label for="inputPhone" class="sr-only">Password</label>
45
                <input type="number" name="inputPhone" id="inputPhone" class="form-control" placeholder="Phone" required>
46
47
                <button id="btnSignUp" class="btn btn-lg btn-primary btn-block" type="submit">Sign up</button>
48
            </form>
49
        </div>
50
51
52
53
        <footer class="footer">
54
            <p>&copy; Company 2015</p>
55
        </footer>
56
57
    </div>
58
</body>
59
60
</html>

Add a request handler called signUp in app.js.

1
app.get('/signUp', function(req, res) {
2
    res.sendFile('signup.html', {
3
        'root': __dirname + '/public/signup'
4
    });
5
});

Save the changes and restart the server. Point your browser to http://localhost:3000 and you should have the application running. Click on the sign-in and sign-up links on the page, and the respective pages should be displayed.

Step 2: Implementing the Sign-Up Functionality

To implement the sign-up functionality, we'll be calling the Python Eve REST API. We'll be calling this API from the Node.js back end since it requires passing the service authentication username and password. So, to prevent exposing the authentication username and password from the scripts, we'll make this call from Node.js.

Let's first create a register request handler to handle the sign-up functionality. 

1
app.post('/register', function(req, resp) {
2
   // Code will be here

3
});

We'll require body-parser to parse the data posted from the form. Install body-parser using NPM package manager.

1
npm install body-parser

Once body-parser has been installed, require that inside app.js.

1
bodyParser = require('body-parser')

To use body-parser to parse the posted form data, we need to use it in our app.

1
app.use(bodyParser.urlencoded({
2
    extended: true
3
}));

Inside the /register handler we can parse the form data as shown:

1
var _firstName = req.body.inputFirstName;
2
var _lastName = req.body.inputLastName;
3
var _username = req.body.inputUsername;
4
var _password = req.body.inputPassword;
5
var _phone = req.body.inputPhone;

We'll be using request to make the call to the Eve APIs. So, install request into the application. 

1
npm install request

Require request in app.py.

1
request = require('request')

Create the options for calling the API as shown:

1
var options = {
2
    url: 'http://127.0.0.1:5000/user/',
3
    method: 'POST',
4
    auth: {
5
        user: 'admin',
6
        password: 'admin'
7
    },
8
    formData: {
9
        firstname: _firstName,
10
        lastname: _lastName,
11
        username: _username,
12
        password: _password,
13
        phone: _phone
14
    }
15
}

We have specified the details for the POST request in the options. admin_username and admin_password  are the authentication username and password required to access the Eve user creation API.

Next, let's use request to make the call.

1
request(options, function(err, res, body) {
2
    if (err) {
3
        console.log(err);
4
        return;
5
    }
6
    console.log('Response: ', res)
7
    console.log('Returned data: ', body)
8
})

Save the changes and restart the server. Point your browser to http://localhost:3000 and navigate to the sign-up screen. Enter the details and click on the sign-up button. Check the terminal window for the response and user creation details returned from the API call.

Step 3: Handling Sign-Up Error

When an error occurs during the sign-up process, we'll pass the error message to the sign-up page. We'll be using a template engine called EJS. First, let's install EJS.

1
npm install ejs

Once done with installation of EJS, add the following line of code to set the view folder and the view engine.

1
var path = require('path');
2
app.set('views', path.join(__dirname + '/public/signup'));
3
app.set('view engine', 'ejs');

Rename signup.html to signup.ejs and add a span to display an error after the submit button.

1
<span style="color:red;"><%= error %></span>

Also, modify the signUp request handler.

1
app.get('/signUp',function(req,res){
2
    res.render('signup',{error:''})
3
});

Next, if any error occurs in the sign-up response, we'll pass it to the sign-up page. If the sign-up process returns no error, we'll redirect the user to the sign-in page.

1
request(options, function(err, res, body) {
2
    if (err) {
3
        return resp.render('signup', {
4
            error: err
5
        })
6
    }
7
    var result = JSON.parse(body)
8
    if (result._status == 'ERR') {
9
        if (result._error.code == '400') {
10
            return resp.render('signup', {
11
                error: 'Username Already Exists!'
12
            })
13
        }
14
        return resp.render('signup', {
15
            error: result._issues.username
16
        })
17
    } else {
18
        console.log('All good');
19
        resp.redirect('/signIn');
20
    }
21
})

Save all the changes and restart the server. Point your browser to http://localhost:3000/signUp and try to register using an existing username. Since the username already exists, you should get an error.

Username already exists error on Sign UpUsername already exists error on Sign UpUsername already exists error on Sign Up

Creating the AngularJS App

Implementing the Sign-In Functionality

AngularJS provides a service called $http which helps in making REST API calls. From the AngularJS docs,

The $http service is a core Angular service that facilitates communication with the remote HTTP servers via the browser's XMLHttpRequest object or via JSONP.

Copy the body content of index.html and create a new file called public/home/home.html.

1
<div class="container">
2
    <div class="header">
3
        <nav>
4
            <ul class="nav nav-pills pull-right">
5
                <li role="presentation" class="active"><a href="#">Home</a></li>
6
                <li role="presentation"><a href="#/signin">Sign In</a></li>
7
                <li role="presentation"><a href="/signUp">Sign Up</a></li>
8
            </ul>
9
        </nav>
10
        <h3 class="text-muted">Angular Node App</h3>
11
    </div>
12
13
    <div class="jumbotron">
14
        <h1>Angular Node App</h1>
15
        <p class="lead"></p>
16
        <p><a class="btn btn-lg btn-success" href="/signUp" role="button">Sign up today</a></p>
17
    </div>
18
19
20
21
    <footer class="footer">
22
        <p>&copy; Company 2015</p>
23
    </footer>
24
25
</div>

In the home folder, create a file called home.js and define the home module and routes config as shown:

1
'use strict';
2
3
angular.module('home', ['ngRoute'])
4
5
.config(['$routeProvider', function($routeProvider) {
6
  $routeProvider.when('/home', {
7
    templateUrl: '../home/home.html',
8
    controller: 'HomeCtrl'
9
  });
10
}])
11
12
.controller('HomeCtrl', [function() {
13
14
}]);

Similarly, replace the HTML code of signin.html with the body content of signin.html. We'll handle sign-in page routing through the AngularJS app. 

Inside the signin folder, create a file called signin.js and add the following route config details.

1
'use strict';
2
3
angular.module('signin', ['base64','ngRoute','myAppService'])
4
5
.config(['$routeProvider', function($routeProvider) {
6
  $routeProvider.when('/signin', {
7
    templateUrl: '../signin/signin.html',
8
    controller: 'SignInCtrl'
9
  });
10
}])
11

In index.html we'll use ngView and route the AngularJS application views. Here is how index.html will look:

1
<!DOCTYPE html>
2
<html lang="en" ng-app="myApp">
3
  <head>
4
    <title>Angular Node App</title>
5
6
   
7
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">
8
9
    <link href="http://getbootstrap.com/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">
10
    <script src="https://code.jquery.com/jquery-2.0.1.min.js"></script>
11
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
12
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.12/angular.js"></script>
13
    <script src="home/home.js"></script>
14
    <script src="signin/signin.js"></script>
15
    <script src="index/index.js"></script>
16
    
17
  </head>
18
19
  <body>
20
21
    <div ng-view></div>
22
  </body>
23
</html>

Inside the index folder, create a file called index.js which will serve as the root file. In index.js we'll inject the different modules created into the myApp app. Here is the index.js file:

1
angular.module('myApp', [
2
  'ngRoute',
3
  'home',
4
  'signin'
5
]).
6
config(['$routeProvider', function($routeProvider) {
7
  $routeProvider.otherwise({redirectTo: '/home'});
8
}]);

Install angular-route using bower and include the reference in index.html.

1
bower install angular-route
1
<script src="../bower_components/angular-route/angular-route.js"></script>

We'll also need to convert the username and password to base64, so install angular-base64.

1
bower install angular-base64

Once installed, add a reference to angular-base64 in index.html.

1
<script src="../bower_components/angular-base64/angular-base64.js"></script>

Set the static path to bower_components in app.js.

1
app.use('/bower_components',  express.static(__dirname + '/bower_components'));

 Inside signin.js, let's create a controller called SignInCtrl.

1
'use strict';
2
3
angular.module('signin', ['base64','ngRoute'])
4
5
.config(['$routeProvider', function($routeProvider) {
6
  $routeProvider.when('/signin', {
7
    templateUrl: '../signin/signin.html',
8
    controller: 'SignInCtrl'
9
  });
10
}])
11
12
.controller('SignInCtrl',['$scope','$http','$base64',function($scope,$http,$base64){
13
}]);

We just created a controller called SignInCtrl in signin.js. We have injected the base64 module to the SignInCtrl.

On sign-in button click, we'll call the above signIn function to authenticate the user. So, first let's add the ngModel directive to the username and password field in the sign-in page.

1
<input type="text" name="inputUsername" id="inputUsername" ng-model="username" class="form-control" placeholder="Email address"  autofocus>        
2
<input type="password" name="inputPassword" id="inputPassword" ng-model="password" class="form-control" placeholder="Password" >

Add the ngClick directive to the Sign In button in signin.html.

1
<button id="btnSignIn" class="btn btn-lg btn-primary btn-block" ng-click="signIn()">Sign in</button>

Inside the signIn function read the username and password from $scope. Once we have the username and password, we'll create the base64 string using angular-base64.

1
$scope.signIn = function() {
2
  
3
    var username = $scope.username;
4
    var password = $scope.password;
5
6
    var authdata = $base64.encode(username + ':' + password);
7
}

Before making a call to the REST APIs, we need to set the necessary headers. We need to set the Access-Control-Request-Headers and Access-Control-Expose-Headers.

1
$http.defaults.headers.common = {"Access-Control-Request-Headers": "accept, origin, authorization"};
2
3
$http.defaults.headers.common = {"Access-Control-Expose-Headers": "Origin, X-Requested-With, Content-Type, Accept"};
4
5
$http.defaults.headers.common["Cache-Control"] = "no-cache";
6
7
$http.defaults.headers.common.Pragma = "no-cache";

We'll also need to set the Authorization header in the $http. Using the base64 authData created using username and password, set the authorization header. 

1
$http.defaults.headers.common['Authorization'] = 'Basic '+authdata;

Next, make the $http GET call to the Python Eve REST APIs.

1
$http({
2
    method: 'GET',
3
    url: 'http://127.0.0.1:5000/user/' + username
4
}).
5
success(function(data, status, headers, config) {
6
    console.log(data);
7
}).
8
error(function(data, status, headers, config) {
9
    console.log(data, status);
10
});

Save all the changes and restart the server. Point your browser to http://localhost:3000/signin. Try to sign in using a valid username and password. Check browser console and you should have the user data. If the authentication fails, you should have an authentication failure error.

Conclusion

In this tutorial, we saw how to use the REST APIs created in the previous tutorial in our AngularJS and Node.js app. We implemented the sign-in and sign-up functionality in this tutorial.

In the next part of this series, we'll use the other APIs to complete our AngularJS app.

Source code from this tutorial is available on GitHub.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.