A Simple App with the AngularJS Framework (Part 2)

In my last post I introduced some major concepts in AngularJS development. I handled models, views and controllers and set up routing. There were a couple of things I did not do, however. The first is the menu bar and the second is authentication. Let’s cover the menu bar first.

The Menu Bar

There are lots of ways to configure a menu bar and I don’t think any one is any better than the others. I could create a custom Angular Directive that takes a DIV and turns it into my nav bar based on a template and a controller. This would be good if I were going to re-use the menu bar time and again.

Alternatively, maybe this is so common that someone else has already done it. There is a great web site – ngmodules.org – that contains a collection of Angular modules that are ready to use. This wouldn’t assist me in learning Angular.

Instead, I’m going to add my code to the main public/index.html file and create another controller. The view will be embedded in the main public/index.html file. Here is the code for the main page:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="jspm_packages/github/twbs/bootstrap@3.3.5/css/bootstrap.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app="testApp">
		<header ng-controller="NavBarController">
			<div id="brand">
				<div class="valign-o">
					<div class="valign-i">
						<i class="fa fa-home"></i>
						<span>{{title}}</span>
					</div>
				</div>
			</div>
			<div id="navigation">
				<ul>
					<li ng-class="{ active: isActive('/welcome')}">
						<a href="#/welcome">Welcome</a>
					</li>
					<li ng-class="{ active: isActive('/flickr')}">
						<a href="#/flickr">Flickr</a>
					</li>
				</ul>
			</div>
			<div id="toolbar">
				<ul>
					<li id="navProfile"></li>
					<li id="navSignIn">
						<i class="fa fa-sign-in"></i>
					</li>
				</ul>
			</div>
		</header>

		<div class="page-host">
			<section ng-view></section>
		</div>

		<script src="jspm_packages/github/components/jquery@2.1.4/jquery.min.js"></script>
		<script src="jspm_packages/github/twbs/bootstrap@3.3.5/js/bootstrap.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular-route@1.4.2/angular-route.min.js"></script>
		<script src="app.js"></script>
	</body>
</html>

I pretty much copied the additional markup from my Aurelia example. There are some minor tweaks to account for the difference in syntax for including specific code. In this case, I am using the isActive() method within the controller to determine whether to add the active class or not. I’ve included the sign-in toolbar and will get to that in the next section – it’s not necessary for the navigation to work. I use a named controller with the ng-controller directive to wire up my controller to this view.

If I compare this to Aurelia, then I did the same thing in the app.html file – that file became the template for my overall page. In Angular, the root document is the template for my overall page.

I already know how to create a controller, so let’s take a look (thanks to myl on Stack Overflow for this code). I added this to the app.js file:

testApp.controller("NavBarController", [ "$scope", "$location",
	function NavBarController ($scope, $location) {
		$scope.title = "Angular";
		
		$scope.isActive = function (viewLocation) {
			return viewLocation === $location.path();
		};
	}
]);

This does what is expected. I would love, however, to have the nav-bar separated. To do that, I need to write a custom Angular Directive. Here is the code within app.js:

testApp.directive("ngNavbar", function () {
	return {
		restrict: "A",
		templateUrl: "partials/navbar.html"
	}
});

This defines an Attribute (restrict: "A") that I can place on another HTML element. When I put the ng-navbar attribute on that element, its innerHTML will be populated with the template I have specified. I need to create that navbar.html file:

<header>
	<div id="brand">
		<div class="valign-o">
			<div class="valign-i">
				<i class="fa fa-home"></i>
				<span>{{title}}</span>
			</div>
		</div>
	</div>
	<div id="navigation">
		<ul>
			<li ng-class="{ active: isActive('/welcome')}">
				<a href="#/welcome">Welcome</a>
			</li>
			<li ng-class="{ active: isActive('/flickr')}">
				<a href="#/flickr">Flickr</a>
			</li>
		</ul>
	</div>
	<div id="toolbar">
		<ul>
			<li id="navProfile"></li>
			<li id="navSignIn">
				<i class="fa fa-sign-in"></i>
			</li>
		</ul>
	</div>
</header>

This is exactly the same code as was wrapped inside the public/index.html file. Now I can remove that code from the public/index.html file:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="jspm_packages/github/twbs/bootstrap@3.3.5/css/bootstrap.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app="testApp">
		<div ng-controller="NavBarController" ng-navbar></div>

		<div class="page-host">
			<section ng-view></section>
		</div>

		<script src="jspm_packages/github/components/jquery@2.1.4/jquery.min.js"></script>
		<script src="jspm_packages/github/twbs/bootstrap@3.3.5/js/bootstrap.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular-route@1.4.2/angular-route.min.js"></script>
		<script src="app.js"></script>
	</body>
</html>

This makes the code much more readable. I could also place the controller in the angular directive I’ve just created as well – a task for another time.

Authentication

As I am doing for the other projects, I’m going to use Auth0 for authentication here. Auth0 has provided an excellent tutorial for this purpose, so I am only going to note the differences.

Installing the libraries was mostly done with jspm:

jspm install angular-cookies
jspm install github:auth0/angular-storage
jspm install github:auth0/angular-jwt

The public/index.html file became the following:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="jspm_packages/github/twbs/bootstrap@3.3.5/css/bootstrap.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app="testApp">
		<div ng-controller="NavBarController" ng-navbar></div>

		<div class="page-host">
			<section ng-view></section>
		</div>

		<script src="jspm_packages/github/components/jquery@2.1.4/jquery.min.js"></script>
		<script src="jspm_packages/github/twbs/bootstrap@3.3.5/js/bootstrap.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular-route@1.4.2/angular-route.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular-cookies@1.4.2/angular-cookies.min.js"></script>
		<script src="jspm_packages/github/auth0/angular-storage@0.0.11/dist/angular-storage.min.js"></script>
		<script src="jspm_packages/github/auth0/angular-jwt@0.0.9/dist/angular-jwt.min.js"></script>
		<script src="http://cdn.auth0.com/js/lock-7.5.min.js"></script>
		<script src="http://cdn.auth0.com/w2auth0-angular-4.js"></script>
		
		<script src="app.js"></script>
	</body>
</html>

That’s lots of scripts at this point – I’d probably handle this with Browserify or some other sort of bundling technology in a production app. This is good for right now. Note that I’m downloading a couple of the libraries from the Auth0 CDN – I’d probably look into bringing these in as local libraries as well. Auth0 publishes lock on their GitHub page.

The partials/navbar.html page also needed a change – I’ve highlighted the changed lines:

<header>
	<div id="brand">
		<div class="valign-o">
			<div class="valign-i">
				<i class="fa fa-home"></i>
				<span>{{title}}</span>
			</div>
		</div>
	</div>
	<div id="navigation">
		<ul>
			<li ng-class="{ active: isActive('/welcome')}">
				<a href="#/welcome">Welcome</a>
			</li>
			<li ng-class="{ active: isActive('/flickr')}">
				<a href="#/flickr">Flickr</a>
			</li>
		</ul>
	</div>
	<div id="toolbar">
		<ul>
			<li id="navProfile">{{nickname}}</li>
			<li id="navSignIn" ng-click="login()">
				<i class="fa fa-{{icon}}"></i>
			</li>
		</ul>
	</div>
</header>

Lines 22 and 24 bind specific variables in the $scope of the NavbarController to these areas. Line 23 uses the ng-click event handler to call the login method in the NavbarController.

Moving on to the app.js, there are two things I must do. Firstly, I have to configure the module and Angular application for authentication. This is straight from the Auth0 Quick Start Guide:

var testApp = angular.module("testApp", [ 'ngRoute', 'auth0', 'angular-storage', 'angular-jwt' ]);

testApp.config(["$routeProvider", "authProvider", function($routeProvider, authProvider) {
	// Route Map
	$routeProvider
		.when("/welcome", {
			title: "Welcome",
			templateUrl: "partials/welcome.html",
			controller: "WelcomeController"
		})
		.when("/flickr", {
			title: "Flickr",
			templateUrl: "partials/flickr.html",
			controller: "FlickrController"
		})
		.otherwise({
			redirectTo: "/welcome"
		});

	authProvider.init({
		domain: "DOMAIN.auth0.com",
		clientID: "YOUR-CLIENT-ID"
	});
}]);

// This hooks all auth events to check everything as soon as the app starts
testApp.run(function (auth) {
	auth.hookEvents();
});

Line 3 brings in all those libraries that Auth0 said I needed. Line 5 adds the authProvider via dependency injection. The authProvider is provided by Auth0. Line 22-25 actually configures the Auth0 settings. Remember to inject your own domain and clientID here. Finally, line 29-31 ensures all the authentication events are captured as the application starts.

The other area of concern is the NavbarController. Here is the new one:

testApp.controller("NavBarController", [ "$scope", "$http", "auth", "store", "$location",
	function NavBarController ($scope, $http, auth, store, $location) {
		$scope.title = "Angular";
		$scope.nickname = "";
		$scope.icon = "sign-in";

		$scope.isActive = function (viewLocation) {
			return viewLocation === $location.path();
		};

		var profile = store.get("profile");
		if (profile) {
			$scope.nickname = profile.name || profile.nickname;
			$scope.icon = "sign-out";
		};

		$scope.login = function() {
			if ($scope.icon === "sign-out") {
				$scope.nickname = "";
				$scope.icon = "sign-in";
				auth.signout();
				store.remove("profile");
				store.remove("token");
			} else {
				auth.signin({}, function (profile, token) {
					// Success callback
					store.set("profile", profile);
					$scope.nickname = profile.name || profile.nickname;
					store.set("token", token);
					$scope.icon = "sign-out";
					$location.path("/");
				}, function () {
					// Error callback
					alert("Auth0 Error!!!!");
				});
			}
		}
	}
]);

There are two new scope variables. The $scope.nickname will be blank when the user is not logged in and will be filled with something when the user is logged in. The $scope.icon will either be “sign-in” or “sign-out” – this changes the icon that is displayed.

From line 82-86, I set up the initial values of the nickname and icon based on the localStorage (represented by the store variable). The default case is the user is unauthenticated. As a result, I only need to change things if the user is authenticated – i.e. when something is in the profile.

The $scope.login() method is called when the user clicks on the authenticator icon. If the user is signed in, then the user is logged out. If the user is not signed in, then I pop up the Auth0 sign-in window and wait for soemthing to come back. A successful return means that the user is logged in, so I store the token and profile and update the nav bar view.

An Authenticated Page

In my Aurelia review, I added an authenticated page. This page only appeared in the navigation when I was authenticated. It also grabbed data from the backend and displayed it. I wanted the same thing here. First of all, I need an authenticated Web API – changes to server.js:

var express = require("express"),
	jwt = require("express-jwt"),
	morgan = require("morgan"),
	staticFiles = require("serve-static"),
	spells = require("./spells.json"),
	config = require("./config.json");

var app = express();

// Check that the JWT is signed by us
var jwtCheck = jwt({
  secret: new Buffer(config.clientSecret, 'base64'),
  audience: config.clientID
});

// Set the port to listen on
app.set("port", process.env.PORT || 3000);

// Set up logging
app.use(morgan("combined"));

// Set up static files within public
app.use(staticFiles("public"));

// Set up a JWT Check for the /api/spells layer
app.use("/api/spells", jwtCheck);

// Set up the spells endpoint
app.get("/api/spells", function (request, response) {
	response.send(spells);
});


// Listen on the TCP port
app.listen(app.get("port"), function () {
	console.log("Listening on port " + app.get("port"));
});

The spells.json file will be returned when I send an authenticated request to the backend for URI /api/spells. An authenticated request is a request with a valid JSON Web Token in the Authorization header. Your config.json should look like this:

{
	"domain": "YOUR-DOMAIN.auth0.com",
	"clientID": "YOUR-CLIENT-ID",
	"clientSecret": "YOUR-CLIENT-SECRET"
}

Ensure you replace the appropriate values from your configuration in Auth0. Now that I have an authenticated API, I need to display it. Firstly, let’s create a new route for “/spells” to go to the new page:

testApp.config(["$routeProvider", "authProvider",
	 function($routeProvider, authProvider) {
		// Route Map
		$routeProvider
			.when("/welcome", {
				title: "Welcome",
				templateUrl: "partials/welcome.html",
				controller: "WelcomeController"
			})
			.when("/flickr", {
				title: "Flickr",
				templateUrl: "partials/flickr.html",
				controller: "FlickrController"
			})
			.when("/spells", {
				title: "Spells",
				templateUrl: "partials/spells.html",
				controller: "SpellsController"
			})
			.otherwise({
				redirectTo: "/welcome"
			});

		authProvider.init({
			domain: "YOUR-DOMAIN.auth0.com",
			clientID: "YOUR-CLIENT-ID"
		});
	}
]);

Lines 19-23 add the new route to the spells page. I also need a Controller and a View. The Controller is as follows:

testApp.controller("SpellsController", [ "$scope", "$http", "auth", "store",
	function SpellsController ($scope, $http, auth, store) {
		$scope.heading = "Spells";
		$scope.spells = [];
		var url = "/api/spells";
		var headers = {
			"Accept": "application/json"
		};

		// Add the authorization token if we are authenticated
		if (auth.isAuthenticated) {
			headers.Authorization = "Bearer " + store.get("token");
		}

		$http.get(url, {
			"withCredentials": true,
			"responseType": "json",
			"headers": headers
		}).success(function (data, status, headers, config) {
			$scope.spells = data;
		}).error(function () {
			console.error("Error retrieving spells");
		});
	}
]);

The “magic” (such that it is) is in lines 89-91 – if the user is authenticated, I add an Authorization header with the JSON Web Token in it. That is sent with the normal headers. Once the response comes back, I assign the result to the spells variable in the scope. My partials/spells.html view is simple:

<h2>{{heading}}</h2>

<div id="spellList">
	<ul>
		<li ng-repeat="spell in spells">
			{{spell.id}}
		</li>
	</ul>
</div>

The spells variable in the scope is an array. I iterate over that array, pulling out the ID. You should get a bullet list of numbers when this is working.

There are a couple of problems with this version of the code (although it does work). Firstly, the Spells link shows up even when the user is not authenticated. This means that you will see the error message in the console. Secondly, the user gets logged out on page refreshes. This is less than ideal. Fortunately, Auth0 has provided a recipe for the latter issue. Place the following in your app.js file:

// This hooks all auth events to check everything as soon as the app starts
testApp.run([ "$rootScope", "auth", "store", "jwtHelper", "$location",
	function ($rootScope, auth, store, jwtHelper, $location) {
		auth.hookEvents();

		$rootScope.$on("$locationChangeStart", function() {
			var token = store.get("token");
			if (token) {
				if (!jwtHelper.isTokenExpired(token)) {
					if (!auth.isAuthenticated) {
						auth.authenticate(store.get("profile"), token);
					}
				} else {
					$location.path("/");
				}
			}
		});
	}
]);

This code replaces the testApp.run() method. It’s a little different than the version provided by Auth0 – this version takes advantage of the dependency injection in AngularJS v1.4. The version provided by Auth0 is for AngularJS v1.2.

This leaves making the Spells link disappear in the navigation. I already have the auth variable available in the NavBarController so I can create a new isAuthenticated() method and use it the same way as I did the isActive() method:

		$scope.isAuthenticated = function() {
			return auth.isAuthenticated;
		};

Now I can adjust the partials/navbar.html to change the Spells link to be authenticated.

<li ng-class="{ active: isActive('/spells'), 'auth-hide': !isAuthenticated()}">
  <a href="#/spells">Spells</a>
</li>

The auth-hide class is defined in styles/site.css to set display: none.

Note how I check authentication in multiple places. This goes to the “don’t trust the user” principal. I ensure the user can’t see the Spells area. If, however, the user has bookmarked the URI, then I ensure that the authentication is not passed to the backend and hence the data is not shown. If I were being particularly paranoid, I would ensure that a different message was shown and the request was not sent to the backend.

Wrapping Up

That’s it for the Angular test. Over the course of the last two posts, I’ve created controllers, views, routing, authentication and custom directives. This is definitely more complex than Aurelia, but it also has a bigger community, better support (including books, videos, tutorials) and more features. If I were deciding on something other than my own project, I would likely use AngularJS over Aurelia. (This is, of course, before I have investigated Ember, Meteor or React/Flux).

There is a big thing coming though. Angular 2 is the “next version of Angular” and promises to utilize all the features of ECMAScript 6. This warrants it’s own investigation once the code base is a little further along. However, it’s a forklift upgrade, although the Angular team says they will support “Incremental” updates by installing both Angular 1.x and 2.x at the same time. It doesn’t sound ideal.

If you want the code from my small tutorial here, it’s on my GitHub Repository.

A Simple App with the AngularJS Framework (Part 1)

In my last post I introduced concepts for MVC and MVVM and said I would be delving into the code for a three page application – a home page, a page that loads from a remote REST interface and an authenticated page. These three pages provide enough of a look into each framework to allow me to understand the framework and decide on which one I want to use long term. Today is all about AngularJS.

Bootstrapping AngularJS

Before we can do anything with AngularJS, we need to get it into our application. We did the same thing with Aurelia when we covered that and I fully expect to do the same thing with the other frameworks. Somehow, your page needs to know about the framework. Firstly, let’s install AngularJS:

jspm install angular

Now let’s adjust the public/index.html file to load it:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
	</head>
	<body ng-app>
		<h1>Hello {{"World" + "!"}}</h1>
		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
	</body>
</html>

The interesting code is highlighted. Firstly, let’s discuss the ng-app Angular Directive. You will sometimes see this referred to as the ngApp directive. If the directive is being used declaratively (i.e. in HTML), then it is represented as all lower case with a dash. If it’s being used in code then it’s represented as camel-case with no dash. They mean the same thing. Directives are indications that a specific behavior needs to be attached to an element. In this case, the ng-app directive tells Angular that it needs to process the body element (i.e. the whole application). If you want Angular to process only a little bit of the page, you can do that too.

Note the double curly-brackets in the h1 element. That’s an Angular Expression and allows you to embed basically any JavaScript expression inside them. More importantly, you can inject code and variables that are “in-scope” within an Angular expression. This is more useful when I talk about views – for now, just know that when you see the double curly brackets, you are looking at an Expression that will get evaluated before display.

We’ve done a whole lot of mark-up before bringing in the JavaScript. The normal thing to do these days is to load scripts right at the end of the page. When Angular loads, it looks for the directives and gets to work. You could just as easily placed the script tag in the head of the document. This is just “more normal”.

The Welcome Page

When we introduced the first page in the Aurelia tutorial, there was already a bunch of stuff around routing, controllers and views. You don’t actually need that in an Angular app – you can just start with a single page. Let’s augment our public/index.html page with the additional code to produce the Welcome page:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app>
		<section ng-init="fn='Adrian';ln='Hall'">
			<h2>Enter Your Name</h2>
			<form role="form">
				<div class="form-group">
					<label for="fn">First Name</label>
					<input type="text" ng-model="fn" class="form-control" id="fn" placeholder="first name">
				</div>
				<div class="form-group">
					<label for="ln">Last Name</label>
					<input type="text" ng-model="ln" class="form-control" id="ln" placeholder="last name">
				</div>
				<div class="form-group">
					<label>Full Name</label>
					<p class="help-block">{{fn + " " + ln}}</p>
				</div>
			</form>
		</section>

		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
	</body>
</html>

Even if you haven’t included a stylesheet, this will demonstrate the point. I have made an ad-hoc Angular Model. It’s initialized with another Angular directive – ng-init provides the initial values for the two fields. I’ve then bound those two fields to text input boxes with the ng-model directive. Finally, I’m using an angular expression to compute the full name. Start changing the text in the text-boxes and you will see the full name change along with it. This is data-binding in action.

Note that the documentation for ng-init tells you that this is a bad way to do things. You should use a controller instead. Good idea – let’s do that!

Adding Controllers

Now that I have a view working (albeit embedded into the main page), I need to develop a controller as well. Angular conventions tell me to wrap all the logic about the controller (and anything else I use) into an Angular Module. Let’s take a look at a new file: public/app.js:

"use strict";

var testApp = angular.module("testApp", []);

testApp.controller("WelcomeController", function () {
	this.fn = "Adrian";
	this.ln = "Hall";

	this.fullName = function () {
		return this.fn + " " + this.ln;
	}
});

This contains the same model parameters as before (fn and ln) and a function to calculate the full name. I want to adjust the HTML view in public/index.html so that it uses the controller instead of the embedded model now:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app="testApp">
		<section ng-controller="WelcomeController as welcome">
			<h2>Enter Your Name</h2>
			<form role="form">
				<div class="form-group">
					<label for="fn">First Name</label>
					<input type="text" ng-model="welcome.fn" class="form-control" id="fn" placeholder="first name">
				</div>
				<div class="form-group">
					<label for="ln">Last Name</label>
					<input type="text" ng-model="welcome.ln" class="form-control" id="ln" placeholder="last name">
				</div>
				<div class="form-group">
					<label>Full Name</label>
					<p class="help-block">{{welcome.fullName()}}</p>
				</div>
			</form>
		</section>

		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
		<script src="app.js"></script>
	</body>
</html>

The changed lines are highlighted. First off, our ng-app statement says “I’m an angular app and module testApp contains my stuff”. The next line says “this section uses the WelcomeController as it’s scope and I’m going to name it welcome within this section”. The ng-controller directive defines a controller association. The two input boxes have had their ng-model statements changed so that they reference the fn and ln variables within the WelcomeController. Finally, my help-block has changed. Instead of an embedded expression to calculate the full name, I’m using a function.

Running this will do the same thing as before, except now I am using a controller instead of default actions. Hopefully, you will see that writing a controller is easy and writing a view is also easy. You can embed them or separate them from your main file.

Routing

I’ve gotten to the point where I have a view (embedded in the page) and a controller (in a separate file). I want to add routing such that when I can handle multiple pages within the same application and the view and controller are separated.

This is a multi-step process. Step 1 is to add routing into the application config. I do this in my app.js file:

"use strict";

var testApp = angular.module("testApp", [ 'ngRoute' ]);

testApp.config(["$routeProvider", function($routeProvider) {
	$routeProvider
		.when("/welcome", {
			templateUrl: "partials/welcome.html",
			controller: "WelcomeController"
		});
}]);

I am declaring a dependency on ngRoute – the Angular Routing module – when I create the module. I also need to bring in the angular-route module in my main page. More on that later. Note that you don’t have to use the Angular provided router. There are others out there (most notably one called UI-Router) that provide different functionality. The core is the same though, so I’m just going to use the standard one.

Once I’ve declared the dependency on ngRoute, I can create a route-map. Right now, there is only one route – the /welcome URI maps to a template and a controller. Note how dependency-injection happens here. I am injecting the $routeProvider and then using it to generate the route-map.

To install the angular-route module, do this:

jspm install angular-route

Don’t forget to add it to the public/index.html as well – I’ll show that when I show off the new file later on.

Another place where dependency injection happens is in the route-enabled controller:

testApp.controller("WelcomeController", [ '$scope',
	function WelcomeController ($scope) {
		$scope.fn = "Adrian";
		$scope.ln = "Hall";

		$scope.fullName = function () {
			return $scope.fn + " " + $scope.ln;
		}
	}
]);

Instead of using this, I’m using a $scope variable. This allows me to access the internals of the model without using an ngController directive to associate the view to the controller.

So that’s the controller – what about the view? I’ve created a new directory: partials and created a welcome.html file within that directory to contain the view:

<h2>Enter Your Name</h2>
<form role="form">
	<div class="form-group">
		<label for="fn">First Name</label>
		<input type="text" ng-model="fn" class="form-control" id="fn" placeholder="first name">
	</div>
	<div class="form-group">
		<label for="ln">Last Name</label>
		<input type="text" ng-model="ln" class="form-control" id="ln" placeholder="last name">
	</div>
	<div class="form-group">
		<label>Full Name</label>
		<p class="help-block">{{fullName()}}</p>
	</div>
</form>

This is the contents of the section element within the main page. I’ve removed the welcome. tags on all the angular directives and expressions – those are now part of the scope and the scope is the default, so there is no reason to qualify it. My final change is to the public/index.html. I need to remove the view code and replace it with something that specifies the ng-view directive. The ng-view directive tells Angular where to place the compiled view.

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title>Angular Test Site</title>
		<link rel="stylesheet" href="jspm_packages/npm/font-awesome@4.3.0/css/font-awesome.min.css">
		<link rel="stylesheet" href="styles/site.css">
	</head>
	<body ng-app="testApp">
		<section ng-view></section>

		<script src="jspm_packages/github/angular/bower-angular@1.4.2/angular.min.js"></script>
		<script src="jspm_packages/github/angular/bower-angular-route@1.4.2/angular-route.min.js"></script>
		<script src="app.js"></script>
	</body>
</html>

You can see the ng-view directive at line 10. I’ve also brought in the angular-route module at line 13.

If you run this application as before, you will note that nothing is displayed. However, remember when I was doing the Aurelia tutorial that the URLs looked something like http://localhost:3000/#/welcome – put in that and you will get the same activity that we have had all along. This time it’s in a reusable controller and template view.

I can add a “default route” using an otherwise() statement in the route map:

testApp.config(["$routeProvider", function($routeProvider) {
	$routeProvider
		.when("/welcome", {
			templateUrl: "partials/welcome.html",
			controller: "WelcomeController"
		})
		.otherwise({
			redirectTo: "/welcome"
		});
}]);

This basically says “here is my route map, but if you don’t recognize anything, display the welcome page”.

Let’s extend the controller slightly. The Aurelia tutorial had a submit button – the application provided an alert when you clicked on the submit button. Let’s add that functionality:

testApp.controller("WelcomeController", [ '$scope',
	function WelcomeController ($scope) {
		$scope.fn = "Adrian";
		$scope.ln = "Hall";

		$scope.fullName = function () {
			return $scope.fn + " " + $scope.ln;
		}
		
		$scope.submit = function () {
			alert("Hello " + $scope.fn + " " + $scope.ln);
		}
	}
]);

I also need to update the view in partials/welcome.html:

<h2>Enter Your Name</h2>
<form role="form">
	<div class="form-group">
		<label for="fn">First Name</label>
		<input type="text" ng-model="fn" class="form-control" id="fn" placeholder="first name">
	</div>
	<div class="form-group">
		<label for="ln">Last Name</label>
		<input type="text" ng-model="ln" class="form-control" id="ln" placeholder="last name">
	</div>
	<div class="form-group">
		<label>Full Name</label>
		<p class="help-block">{{fullName()}}</p>
	</div>
	<button id="submit" ng-click="submit()">Submit</button>
</form>

I’m using another directive – ng-click – to wire up the event handler so that the user can click on the Submit button.

To finish up this first page, I also want to get bootstrap installed. This was just a case of using jspm to install it and then adding the CSS and JS files to the index.html file. I’ve skipped that step in these instructions, but the code is in the repository.

Adding a Second Page

Now that I have my first page configured, I want to create a second page – the flickr example from the Aurelia app. To do that, I need to add a controller and a template (easy enough given the Aurelia app has pretty much provided those for me) and then I need to wire up a route. Let’s first of all wire up the route:

testApp.config(["$routeProvider", function($routeProvider) {
	$routeProvider
		.when("/welcome", {
			templateUrl: "partials/welcome.html",
			controller: "WelcomeController"
		})
		.when("/flickr", {
			templateUrl: "partials/flickr.html",
			controller: "FlickrController"
		})
		.otherwise({
			redirectTo: "/welcome"
		});
}]);

I need to create the template view in partials/flickr.html:

<h2>{{heading}}</h2>

<div class="row">
	<div class="col-sm-6 col-md-4" ng-repeat="image in images">
		<a class="thumbnail">
			<img style="width: 260px; height: 180px;" src="{{image}}"/>
		</a>
	</div>
</div>

I’m using another Angular directive here – ng-repeat – this duplicates a given block while iterating over an array. I’m using it to generate multiple thumbnails based on the array “images”. This is pretty much the same as the Aurelia version (with slightly different semantics for the repeating block). Now, on to the controller:

testApp.controller("FlickrController", [ "$scope", "$http",
	function FlickrController ($scope, $http) {
		$scope.heading = "Flickr";
		$scope.images = [];
		$scope.tags = "ranier";
		var url = "http://api.flickr.com/services/feeds/photos_public.gne";

		$http.jsonp(url, {
			params: {
				"tags": $scope.tags,
				"tagmode": "any",
				"format": "json",
				"jsoncallback": "JSON_CALLBACK"
			},
			"responseType": "json"
		}).success(function (data, status, headers, config) {
			$scope.images = data.items.map(function (v) {
				return v.media.m;
			});
		});
	}
]);

There is some very interesting stuff going on here. First of all, I am injecting the $http object via dependency injection. This allows me to do HTTP calls. I’m going to use it to call the Flickr API via JSONP. Note the jsoncallback parameter though. That’s very important. The JSONP element normally is returned via a callback which is the object wrapped in a function call. That function call must be “JSON_CALLBACK” so that the JSON object gets decoded properly. This took me quite a while to figure out. The $http methods all produce promises. However, this isn’t the Promise that I’ve come to love – it’s different. That means I call success() and error() instead of then() and catch() like normal.

Once I’ve got the data, I assign it to images (mapping each element along the way) and the data binding takes care of the rest.

Thoughts so far

Obviously, I’m going to compare the Angular version to the Aurelia version. Angular feels more fully featured than Aurelia and the community in Angular is obviously much bigger. One of the things I found particularly intriguing was the decoupling of the data source from the models. Aurelia has yet to tackle the data problem – they are concentrating on controllers and views.

However, for controllers and views (and particularly multiple controllers and views), Angular just seems much more “heavy” than the Aurelia counterpart. I wrote less code in the Aurelia version than the Angular version.

More To Come!

I haven’t finished yet, but I’ve written a lot of code and learned a lot about Angular. The Angular app was so big that I had to split it into two posts. In the next post I’ll take a look at implementing the menu bar and authentication. Stay tuned!

MVC, MVVM and Frameworks

I’ve been writing a whole bunch about MVC architectures – client side and server side.  But I hit a problem.  You see, MVC and MVVM are pretty simple concepts.  Here is a typical diagram that I see when looking at MVC descriptions:

blog-08012015-1

It’s nice and simple.  The controller loads the model and passes some form of data to the View.  The problem is this – where is the user and where is the data?  How do these actually interact?  This is actually a key point in understanding the architecture and the place that frameworks – any framework – occupies in the architecture.  I think the following is a much more representative architectural diagram:

blog-08012015-2

This makes more sense to me.  The user submits a request to a dispatcher.  The dispatcher decides which controller to pass the request to.  The controller asks the adapter to give it one or more models to complete the request.  In the case of MVVM, these models are transitioned into a View-Model, usually through some sort of data binding.  This new model (or view-model) is passed into the View rendering system, which renders the appropriate view and kicks it back to the core dispatcher so that the dispatcher can respond to the user.

It’s much more messy than the plain MVC (or MVVM) design pattern.  However, it’s implementable and I can see the pieces I need to implement in order to achieve the desired web application.  This architecture can be implemented on the client side or the server side and both sides have frameworks that assist.

Frameworks provide some sort of functionality that allow you to ignore the boiler-plate code that inevitably comes with writing such an architecture.  Most frameworks have some sort of dispatcher (normally called a router, but they do much more than that) and most frameworks have some sort of adapter logic (mostly called an ORM or Object Relational Mapper).  In between, frameworks enforce a pattern for controllers, models and views that can be used to enforce consistency across the application.

On the server side, I have two go-to languages – C# and JavaScript.  I use ASP.NET as my framework of choice on the C# server side.  I can map my visual directly to ASP.NET:

  • ASP.NET provides the dispatcher, with an ability to configure a route map in it’s startup class.
  • The Controller class can be inherited to create custom controllers
  • The Model is a plain-old class
  • The View is handled by Razor syntax
  • The Adapter is generally handled by Entity Framework.

For server-side JavaScript, the mapping is a little more messy:

I haven’t really gotten into Models and Adapters, although I can see libraries such as Mongoose (for MongoDB) playing a part there.  However, there are Node/Express MVC frameworks out there – I want to investigate Locomotive and SailsJS at some point, for example.

On the client side, things are definitely more messy.  There are a host of different frameworks – Angular, Aurelia, Ember, Knockout, Meteor, React / Flux, along with a host of others.  I’ve found the TodoMVC site to have a good list of frameworks worth looking at.  Some of these are being upgraded to handle ES2015 syntax, some are already there and some are never going to be there.

One thing to note about frameworks.  They are all opinionated.  ASP.NET likes the controllers to be in a Controllers namespace.  Angular likes you to use directives.  Aurelia likes SystemJS and jspm.  Whatever it is, you need to know those opinions and how they will affect things.

The web isn’t the only place one can use frameworks.  The MVC architecture is not limited to web development – it’s constant across applications of any complexity.  For example, you can see MVC in WinForms, Mobile applications, Mac OSX Applications and Linux Applications.

I want my application to be rendered client-side, which means I need to take a look at client-side frameworks.  My working list is:

I’m not going to bother with Backbone, Meteor, Knockout or any other older or smaller framework.  This is my own time and I don’t want to spend a ton of time on investigation.  I pretty much know what Aurelia can provide.  To investigate the others I needed a small site I could implement – something that wasn’t “just another task organizer” (TodoMVC).  To that end, I decided to create a three page application.

  • Page 1 – the home page – will get loaded initially and contain a Polymer-based carousel
  • Page 2 – a linked page – will load data from the Internet (the Flickr example from the Aurelia app)
  • Page 3 – an authenticated page – will load data from the local server if the user is authenticated

In addition to the three pages, I’m going to ensure that the navigation is separated logically from the actual pages and that – where possible – the pages are written in ES2015.  I want separation of concerns, so I expect the models to be completely separate from the views and controllers.

Each one will be implemented on top of a Node/ExpressJS server that serves up just the stuff needed.  In this way, I will be able to see the install specifics.  You can see my starter project on my GitHub Repository.  I hope you will enjoy this series of blog posts as I cover each framework.

Node, MVC Controllers and ECMAScript 2015

Long time readers of my blog will remember that I previously covered Node and MVC applications in a short tutorial series. At that point, I wrote the controllers and loader in ECMAScript 5.1. The code to load the controllers was this:

  fs.readdirSync("./controllers").forEach(function (file) {
    if (file.substr(-3) === ".js") {
      console.info("Loading Controller " + file);
      var base = "/" + path.basename(file, ".js");
      var route = require("./controllers/" + file);
      app.use(base, route);
    }
  });

The typical controller looked like this:

"use strict";

var express = require("express"),
    path = require("path"),
    config = require("../config.json"),
    extend = require("extend");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js"),
    loginRoute = config.loginRoute || "/account/login";

/**
 * Set of default properties for the rendering engine
 */
function defaultProperties(req) {
  return {
    title: "Unknown",   // Default title in case the developer doesn't set one
    user: req.user
  };
}

/**
 * Render an appropriate view
 */
function view(req, res, viewName, locals) {
  res.render(controller + "/" + viewName + ".html",
    extend({}, defaultProperties(req), locals));
}

/**
 * GET /{controller=Home}/index
 */
function index(req, res) {
  if (!req.isAuthenticated()) {
    res.redirect(loginRoute);
    return;
  }
  view(req, res, "index", { title: "Home" });
}

// Per-route functionality
router.get("/index", index);

// Default route is to GET index
router.get("/", index);

module.exports = router;

That’s a lot of boilerplate code and it’s completely unreadable for mere mortals. I am working on learning ECMAScript 2015 in depth and I thought I would re-visit this topic. Could I make my controller modules into classes and simplify the whole controller configuration?

Step 1: The New Controller Loader

Since my controllers are going to be classes, I knew I was going to need to adjust the loader. My aim here is just to load the controller classes; not to get the perfect class loader. Here is my code:

// MVC Controllers
var controllerList = {};
fs.readdirSync(path.join(__dirname, "controllers")).forEach(function (file) {
	if (file.substr(-3) === ".js") {
		var basePath = path.basename(file, ".js");
		var Controller = require(`./controllers/${file}`);
		controllerList[basePath] = new Controller(basePath);
		app.use(`/${basePath}`, controllerList[basePath].router);
	}
});

This code loops through every single JavaScript file in the controllers directory. For each one, it constructs a basePath. If the controller is called home.js, then the basePath becomes “home”. I then load the javascript file using a standard “require” statement. Since it’s a class, I create a new object passing in the basePath. I expect that object to expose a router parameter and I use that to link in the router to the basePath. I construct the path using an ES6 template string.

Step 2: The Controller – First Pass

One of the concepts I am pretty religious about is this: Don’t over-complicate the solution early. Get it working, then see if you can do something to make the solution simpler, easy to test, read better, more efficient or whatever you want to do. Here is my first controller:

var express = require("express"),
	extend = require("extend");

export default class HomeController {
	constructor(basePath) {
		this.basePath = basePath;
		this.router = express.Router(); //eslint-disable-line new-cap

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.basePath + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	// GET /home/index (or just /home)
	index(request, response) {
		this.renderView(response, "index");
	}
}

One of the things you will note is that this actually has a lot in common with the ECMAScript5 version of the same controller – it’s just in class form. My module exports the controller class by default. That means I can import it with whatever name I want. The constructor stores the base path that it is passed and creates a new router. The constructor also constructs the routes available in the controller. It uses ES6 fat arrows to preserve the “this” variable.

The renderView method combines a dataset with a view and renders a view. Note I’m using ES6 default parameters and the block-level “let” statement – more ES6 features in use.

Finally, I have a method that actually handles a route. Really, the only unique things for this controller are the index() method that handles a route and the route definition in the constructor.

Step 3: Simplify the Code

This controller class actually works, but I can see a bunch of duplicated code. In the constructor, the basePath and router will always be done this way. I’m allowing the underlying system access to the router variable – definitely not what I want. I want the router to be read-only after creation. Also, the renderView() method is going to be boiler plate code – I want to abstract that away. My simplifying thought here is this: let’s create a Controller class with all the common code in it. We can then extend the Controller class to create the HomeController and only include the “differences”. Here is my new Controller.js file:

var express = require("express"),
	extend = require("extend");

export class Controller {
	constructor(basePath) {
		this.prvBase = basePath;
		this.prvRouter = express.Router(); //eslint-disable-line new-cap
	}

	renderView(response, viewName, localData = {}) {
		let viewPath = this.prvBase + "/" + viewName;
		let defaultData = {
			title: "~~~Unknown~~~"
		};
		let data = extend(defaultData, localData);
		response.render(viewPath, data);
	}

	get basePath() {
		return this.prvBase;
	}

	get router() {
		return this.prvRouter;
	}
}

A lot of this code comes from the original home.js code. I’ve converted the basePath and router variables into ES6 getters so that I can make them read-only (assuming one uses the published API). Now, what does an implementation of a controller look like? Let’s look at the new home.js:

import {Controller} from "../mvc/Controller";

export default class HomeController extends Controller {
	constructor(basePath) {
		super(basePath);

		// Route definitions for this controller
		this.router.get("/", (req, res) => { this.index(req, res); });
		this.router.get("/index", (req, res) => { this.index(req, res); });
	}

	index(request, response) {
		this.renderView(response, "index");
	}
}

This is getting much closer to where I want to be. The super() call is for running the constructor of the class I am extending, thus setting up the common code. I still have to define the routes within the constructor, but I don’t have any boiler-plate code.

What else would make this controller object awesome? ECMAScript 7 is defining a concept called decorators. With ES7 decorators, I could theoretically do something like this:

export default class HomeController extends Controller {
    @HttpGet([ "/", "/index" ])
    index(request, response) {
        this.renderView(response, "index");
    }
}

Of course, ES2015 (also known as ES6) is just out and I don’t expect ES7 to be ratified for a number of years, so there is no guarantee that anyone will support ES7 decorators. You can check out the compatibility chart at Kangax. Note that only Babel supports ES7 decorators right now.

I’m going to delve into decorators in another blog post. For now, this mechanism is great for developing an MVC application without the need of libraries beyond the standard ExpressJS.

MVC Architecture – Node Style

In the last three articles I’ve been doing a study of what it takes to do a node app. For those who are starting here, I had a list of requirements:

  1. I need to be able to run a small web server
  2. I need to be able to handle templated views with server-side code
  3. I need to be able to do social authentication
  4. I need to be able to use an MVC architecture
  5. I need to be able to provide a Web API
  6. I need to be able to publish a node app to Azure
  7. I need to be able to edit node applications in Visual Studio 2015

I didn’t like the way I was writing code in the first three articles. It looked a little hacky. I wanted to get a clear separation of concerns – something the MVC pattern provides and something I am using in my ASP.NET vNext projects. I finally got there, but it was a lot of code.

Let’s start with the package.json – I needed a bunch more libraries to do MVC than I was using before. Here is my new package.json file:

{
  "name": "basic-webapp",
  "version": "0.0.1",
  "description": "A Basic View-Controller Web Application",
  "main": "server.js",
  "private": true,
  "scripts": {
    "start": "node server.js"
  },
  "repository": {
    "type": "git",
    "url": "https://github.com/adrianhall/node-stuff"
  },
  "author": "Adrian Hall ",
  "contributors": [
    {
      "name": "Adrian Hall",
      "email": "adrian@shellmonger.com"
    }
  ],
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/adrianhall/node-stuff/issues"
  },
  "homepage": "https://github.com/adrianhall/node-stuff",
  "dependencies": {
    "body-parser": "^1.12.3",
    "cookie-parser": "^1.3.4",
    "ejs": "^2.3.1",
    "express": "^4.12.3",
    "express-partials": "^0.3.0",
    "express-session": "^1.11.1",
    "extend": "^2.0.1",
    "method-override": "^2.3.2",
    "passport": "^0.2.1",
    "passport-auth0": "^0.2.1",
    "serve-favicon": "^2.2.0"
  }
}

Some of these are not strictly necessary. For example, I could happily dispense with the favicon. However, I wanted for the setup to be as complete as possible. Note that I’ve added a script as well – to start the server I now use npm start instead of node index.js. It also starts a different file – server.js.

In order to configure the application, I added a configuration JSON file called config.json. Note that the GitHub Repository has the file config-default.json – that’s because YOU MUST EDIT THIS FILE BEFORE USE. Here is the config-default.json file:

{
  "loginRoute": "/account/login",
  "server": {
    "uri": "http://localhost:3000",
    "port": 3000
  },
  "passport": {
    "auth0": {
      "domain": "{{DOMAIN}}.auth0.com",
      "clientid": "{{CLIENTID}}",
      "clientsecret": "{{CLIENTSECRET}}",
      "connections": [ "facebook", "windowslive", "google-oauth2", "twitter" ]
    }
  }
}

If you remember from the social authentication article, I’m using Auth0 as my social authenticator. That system requires a domain, client ID and client secret from the Auth0 website to function. Replace the appropriate pieces in this file and save it as config.json

To make sure that I don’t check in MY config.json, I’ve added it to the .gitignore file.

Talking of auth0, my auth0-strategy.js file is slightly different as well:

/*eslint-env node */

"use strict";

var passport = require("passport"),
    Auth0Strategy = require("passport-auth0"),
    config = require("./config.json");

var strategy = new Auth0Strategy({
  domain: config.passport.auth0.domain,
  clientID: config.passport.auth0.clientid,
  clientSecret: config.passport.auth0.clientsecret,
  callbackURL: "/account/external-callback"
}, function(accessToken, refreshToken, extraParams, profile, done) {
  return done(null, profile);
});

passport.use(strategy);

// This is not a best practice, but we want to keep things simple for now
passport.serializeUser(function(user, done) {
  done(null, user);
});

passport.deserializeUser(function(user, done) {
  done(null, user);
});

module.exports = strategy;

It reads the config.json file and inserts the information you stored there into the constructor for the Auth0Strategy. Note that I’ve also set up ESLint properly – I’m in a node environment (the first line). If you run eslint auth0-strategy.js, this will pass.

I also changed my callback URL. This is to allow a controller to handle the account activities. More on that later, but you will have to insert the new callback URL into the Auth0 Management console for your app.

The final piece of application code (before we get onto the controllers and views) is the server.js file:

/*eslint-env node */

"use strict";

var express = require("express"),
    http = require("http"),
    path = require("path"),
    fs = require("fs"),
    partials = require("express-partials"),
    ejs = require("ejs"),
    passport = require("passport"),
    cookieParser = require("cookie-parser"),
    session = require("express-session"),
    bodyParser = require("body-parser"),
    methodOverride = require("method-override"),
    favicon = require("serve-favicon");

/**
 * Configure the Express server to serve up the application
 * @param {express} app - the express application object
 * @return - the express application object (pipelining allowed)
 */
function configure(app) {
  // Load the server configuration file
  console.info("Loading Server Configuration");
  var config = require("./config.json");

  // Load the authentication strategy
  console.info("Loading Authentication Strategy");
  var authStrategy = require("./auth0-strategy"); // eslint-disable-line no-unused-vars

  // Set up the port that the server will listen on
  console.info("Setting Listening port");
  app.set("port", process.env.PORT || config.server.port || 3000);

  // Set up the location of the views
  console.info("Setting view location");
  app.set("views", path.join(__dirname, "views"));

  // Set Express to use the EJS view engine
  console.info("Configuring view engine");
  app.engine("html", ejs.renderFile);
  app.set("view engine", "html");

  // Set up express to use layouts with the default layout being in
  // /views/Shared/layout.html
  console.info("Configuring layout engine");
  app.set("view options", { defaultLayout: "Shared/layout" });
  app.use(partials());

  // Set up express to use the passport authentication middleware
  console.info("Configuring Passport authentication");
  app.use(cookieParser());
  app.use(session({
    secret: "app-secret",
    resave: false,
    saveUninitialized: false,
    unset: "destroy"
  }));
  app.use(passport.initialize());
  app.use(passport.session());

  // Set up static file serving
  console.info("Configuring static file serving");
  app.use("/client", express.static(path.join(__dirname, "client")));

  // Provide middleware for decoding JSON, URL-encoded body parts
  console.info("Loading Body Parser Middleware");
  app.use(bodyParser.urlencoded({ extended: false }));
  app.use(bodyParser.json());

  // Allows a controller to override HTTP verbs such as PUT or DELETE
  console.info("Loading Method Overrides");
  app.use(methodOverride());

  // Serve up a default favicon
  console.info("Configuring favicon");
  app.use(favicon(path.join(__dirname, "client/favicon.ico")));

  // Dynamically include controllers in the controllers directory
  console.info("Loading Controllers");
  fs.readdirSync("./controllers").forEach(function (file) {
    if (file.substr(-3) === ".js") {
      console.info("Loading Controller " + file);
      var base = "/" + path.basename(file, ".js");
      var route = require("./controllers/" + file);
      app.use(base, route);
    }
  });

  console.info("Configuring Home Controller");
  app.get("/", function(req, res) {
    res.redirect("/home");
  });

  // Return the app so we can pipeline
  console.info("Finished configuring server");
  return app;
}

/*
 * Configure the application
 */
var server = configure(express());
http.createServer(server).listen(server.get("port"), function () {
  console.info("Express Server listening on port " + server.get("port"));
});

Phew – that’s a lot of code. Fortunately, this is all fairly explanatory with the comments that are in there. The only complicated bit is this piece of code that loads the controllers (highlighted at lines 80-89) The first block loads each javascript file in the controllers directory. For each controller, I compute a base URL. If the controller is called home.js, then the base will be /home. I’m expecting the controller to export an Express Router object – more on that when I get to controllers.

Once I’ve configured all the controllers, I set the default home page to redirect to the root document in the home controller. This is just like ASP.NET when you provide a route configuration that includes {controller=Home}.

The Basic Controller Pattern

Let’s take a look at the home controller (controllers/home.js) so that we can understand the logic that goes into it. The home controller has a home page that renders a view. However, the view only gets rendered if the user is authenticated. If the user is not authenticated, the user is redirected to the account controller:

/*eslint-env node */

"use strict";

var express = require("express"),
    path = require("path"),
    config = require("../config.json"),
    extend = require("extend");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js"),
    loginRoute = config.loginRoute || "/account/login";

/**
 * Set of default properties for the rendering engine
 */
function defaultProperties(req) {
  return {
    title: "Unknown",   // Default title in case the developer doesn't set one
    user: req.user
  };
}

/**
 * GET /{controller=Home}/index
 */
function index(req, res) {
  if (!req.isAuthenticated()) {
    res.redirect(loginRoute);
    return;
  }
  res.render(controller + "/index.html", extend({}, defaultProperties(req), {
    title: "Home"
  }));
}

// Per-route functionality
router.get("/index", index);

// Default route is to GET index
router.get("/", index);

module.exports = router;

First off, I create an Express router. I also compute the controller name based on the filename of the javascript file. Finally, I compute the loginRoute – if it is specified in the configuration, then use that, otherwise I have a default location specified.

The defaultProperties() method returns an object with some information that the layout needs. The req object is not available in the layout and I want to display my name and maybe other information from the authentication object. In addition, I want to ensure that things don’t break just because I didn’t give all the parameters the layout needs for rendering.

The index() method is the handler for the /index route. The initial part just handles redirection if the user is not authenticated. The render() statement renders a view based on the controller – In this case, this is the home controller, so it will look in views/home/index.html for its view.

The extend() statement is an interesting one and is provided by a library. It combines multiple objects together, with an order of precedence. I start with the empty object, add in the default properties, then add in the route specific properties. I suppose I could do something like:

/**
 * Render an appropriate view
 */
function view(req, res, viewName, locals) {
  res.render(controller + "/" + viewName + ".html",
    extend({}, defaultProperties(req), locals));
}

As an appropriate helper. Then the index function becomes:

/**
 * GET /{controller=Home}/index
 */
function index(req, res) {
  if (!req.isAuthenticated()) {
    res.redirect(loginRoute);
    return;
  }
  view(req, res, "index", { title: "Home" });
}

This is maybe slightly more readable, but not necessary.

The final piece of the module wires up the routes relative to the controller – I’ve given two routes, one for / and one for /index – both identical. Thus, when the user browses to /home or /home/index, they get the same page. Finally, I export the router I created. This is the object that the configuration code in server.js gets – it then links it into the main express router using the controller name as the location.

The Basic View Pattern

To go along with the basic controller, I need a basic view. All the views are relative to ./views/{controller} in this pattern. My ./views/home/index.html file is basic indeed:

<h1>Index</h1>

I want that wrapped in a layout. I included the following code in server.js to specify the default location of the layout (assuming one was not specified):

  console.info("Configuring layout engine");
  app.set("view options", { defaultLayout: "Shared/layout" });
  app.use(partials());

This tells me the layout, by default, is in ./views/Shared/layout.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="A basic web application">
  <meta name="author" content="">

  <title><%= title %> | Basic WebApp</title>

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
  <!--[if lt IE 9 ]>
    <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
    <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->

  <link rel="stylesheet" href="/client/layout.css">

</head>
<body>
  <div id="wrapper">
    <nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="navbar-header">
        <a class="navbar-brand" href="/">Basic WebApp</a>
      </div>
      <!-- Top Menu Items -->
      <ul class="nav navbar-right top-nav">
        <li><a href="/account/profile"><%= user.displayName %></a></li>
        <li><a href="/account/logout">
          <i class="fa fa-sign-out"></i>
          <span class="sr-only">Sign Out</span>
        </a></li>
      </ul>
    </nav>
    <section id="page-wrapper">
      <div class="container-fluid">
        <%- body %>
      </div> <!-- /.container-fluid -->
    </section> <!-- /#page-wrapper -->
  </div> <!-- /#wrapper -->

  <script src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
</body>
</html>

I’ve included a default navbar that includes the user display name and a link to the logout. I have not created an /account/profile in this article (and there isn’t going to be one – that’s for you to write). Note that I’ve also added in some CSS (which I’m not going to show off in the article – go check out the GitHub Repository).

This is very similar to the Razor _Shared.cshtml file in ASP.NET. The rendering is a little different due to the change in rendering engine, but it should feel familiar.

The Account Controller

In ASP.NET, the Account Controller was special. It’s no different here. I’m only doing Social Authentication in this version. In the Auth0 management portal, I’ve turned on Twitter, Facebook, Windows Live and Google authentication. I have not changed the API keys from the Auth0 development keys. If you were deploying this in production (and paying Auth0), then you would definitely want to register your own keys with Auth0.

If you click on your app and then on Connections (along the top), you should see something like this:

blog-code-0521-1

Now that is done, let’s take a look at the controller controllers/account.js:

/*eslint-env node */

"use strict";

var express = require("express"),
    passport = require("passport"),
    path = require("path"),
    config = require("../config.json");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js");

/**
 * Build a URL for a specific provider based on the configuration and
 * the provider name
 */
function buildurl(provider) {
  var server = config.server.uri || "http://localhost:3000";

  var url = "https://" + config.passport.auth0.domain + "/authorize" +
    "?response_type=code&scope=openid%20profile" +
    "&client_id=" + config.passport.auth0.clientid +
    "&redirect_uri=" + server + "/" + controller + "/external-callback" +
    "&connection=" + provider;

  return url;
}

Up to this point, it’s a regular controller. I’ve defined a private function for building a URL to link into the Auth0 system. I’m going to pass these URLs as locals in the login method – speaking of which:

/**
 * GET /{controller}/login
 */
function login(req, res) {
  var locals = {
    layout: false,
    connections: {}
  };
  var connections = config.passport.auth0.connections || [];
  for (var i = 0; i < connections.length; i++) {
    locals.connections[connections[i].replace("-","_")] = buildurl(connections[i]);
  }

  res.render(controller + "/login.html", locals);
}

/**
 * GET /{controller}/logout
 */
function logout(req, res) {
  req.logout();
  res.redirect("/");
}

// Wire up Per-route functionality
router.get("/login", login);
router.get("/logout", logout);

This section is all about wiring up the login and logout routes. The login route will display the ./views/account/login.html view, and I am passing in the list of connections from the config.json file. You can have as many as you want here.

// Social Identity callback - set this in the Auth0 Manage App page
router.get(
  "/external-callback",
  passport.authenticate("auth0", {
    failureRedirect: "/" + controller + "/failure-callback"
  }),
  function (req, res) {
    if (!req.user) {
      throw new Error("user is null");
    }
    res.redirect("/");
  }
);

module.exports = router;

Finally, we need to handle the callback. This is set in the auth0-strategy file and this file – in two places. Firstly, in the buildurl() method and then again in the route to handle the external callback. You can specify a new route /failure-callback that displays a “Oh Noes – Something bad happened” view, or you can just let it 404. If everything is successful, we redirect back to the home page – this time authenticated.

The ./views/account/login.html is a complete HTML page. I’ve specified “layout: false” in the locals – a signal to the rendering engine to not use a layout file:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">

  <!-- Bootstrap, Bootstrap-Social, Font-Awesome -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

  <!-- My minimal stylesheet -->
  <link rel="stylesheet" href="/client/bootstrap-social.css">
  <link rel="stylesheet" href="/client/login.css">
  <title>Login | Basic WebApp</title>
</head>
<body>
  <div id="outer">
    <h2>Login with your Social Provider</h2>
    <div class="row">
      <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 social-buttons">
        <a class="btn btn-block btn-social btn-twitter" href="<%= connections.twitter %>">
          <i class="fa fa-twitter"></i> Sign in with Twitter
        </a>
      </div>
      <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 social-buttons">
        <a class="btn btn-block btn-social btn-facebook" href="<%= connections.facebook %>">
          <i class="fa fa-facebook"></i> Sign in with Facebook
        </a>
      </div>
      <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 social-buttons">
        <a class="btn btn-block btn-social btn-microsoft" href="<%= connections.windowslive %>">
          <i class="fa fa-windows"></i> Sign in with Microsoft
        </a>
      </div>
      <div class="col-xs-12 col-sm-6 col-md-6 col-lg-6 social-buttons">
        <a class="btn btn-block btn-social btn-google" href="<%= connections.google_oauth2 %>">
          <i class="fa fa-google"></i> Sign in with Google
        </a>
      </div>
    </div>
  </div>
</body>
</html>

I’ve downloaded bootstrap-social.css and put it in my client static area for this.

With all this code, I now have a complete basic web app that authenticates via one of four social logins and produces a nice Bootstrap-enabled front page.

You can get all the code from my GitHub Repository.

View Logic – Node Style

I’m currently in the middle of a Node investigation. Here was the list of my requirements:

  1. I need to be able to run a small web server
  2. I need to be able to handle templated views with server-side code
  3. I need to be able to do social authentication
  4. I need to be able to use an MVC architecture
  5. I need to be able to provide a Web API
  6. I need to be able to publish a node app to Azure
  7. I need to be able to edit node applications in Visual Studio 2015

I started the process in the last article by installing NodeJS and writing a simple web server that served static content. I want to use a rendering engine on the server side to generate some views – the V part of an MVC architecture. That’s the subject of todays article.

Express has a favorite – Jade – and I don’t like it. I’m looking for something more akin to the Razor cshtml files in ASP.NET, and I believe I found it in EJS. It takes your HTML, embeds Server-side Javascript, renders the resulting HTML and sends it to the client.

There are a lot of view template engines for Express. With ASP.NET, you pretty much have Razor. Sure – there are likely others, but Razor has the lions share of the attention to the point that it’s pretty worthless to discuss anything else. Not so in Node. There are a lot of templating engines. I looked for one that was easy to configure and closest to what Razor supplies. If you like something else, go for it.

Step 1: Include EJS as a library

Just like express, ejs comes in with a library and I need to use npm install to bring it in. I also want to support layout files (which is a concept from ASP.NET again) – that is provided by the express-partials library, so I’ll install that as well:

npm install --save ejs express-partials

This command will also add the libraries to your package.json file.

Step 2: Wire up EJS as the View Renderer

I also need to tell Express to use EJS as the view renderer. This is done in my index.js file:

var express = require("express");
var partials = require("express-partials");
var ejs = require("ejs");

var app = express();

// Set Express to use the EJS view engine
app.engine("html", ejs.renderFile);
app.set("view engine", "html");

// Set up express to use layouts
app.use(partials());

// Anything under /client is served as a static file
app.use("/client", express.static("client"));

app.get("/", function(req, res) {
  res.render("index", {
    title: "Index Page (from index.js)"
  });
});

var server = app.listen(3000, function() {
  var port = server.address().port;
  console.log("Listening on http port %d", port);
});

I’ve changed four things here. Firstly, I’ve brought in the ejs and express-partials libraries at the top. Secondly, I’ve set the view engine to be ejs. This is always done in two steps. Specify that a certain extension (in my case – “.html”) is to use a specific rendering technology (in my case the ejs file renderer), and then specify that the default view engine is to use that extension. In other words “when I ask for a .html file to be rendered, pass it through the EJS renderer”. My third change is to configure express-partials – this is the fancy express library term for using layout controls. Finally, I’ve altered the app.get line for the home page route to render a view called index and passed it an object with information that I can use in the rendering.

Step 3: Write a Layout

The views are stored in the views directory, unless you change it. EJS looks for a special file called layout.html (it’s .html because I changed the extension when I added the rendering engine – otherwise, it would be layout.ejs). Here are the contents:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title><%= title %> | Basic WebApp</title>
</head>
<body>
  <%- body %>
</body>
</html>

In an ideal world (and we strive for ideal), the title will be replaced by the title property of the object passed into the res.render() method, and the body will be replaced by the contents of our actual view. Speaking of which, I need to write a views/index.html view. Here are the contents:

<h1>Hello World from EJS views/index.html</h1>

You can run the server at this point using node index.js and browse to http://localhost:3000 – this should give you what you expect. Bring up the F12 Developer Tools and check out the HTML – make sure the layout.html is combined with the index.html.

In learning about EJS, I like that the syntax closely resembles the ASP.NET Razor logic – minus the shift across to Javascript. This was also a lot closer to the ideal of having control over the HTML rather than delegating that to code I didn’t write (like Jade or Handlebars, for instance). I may be overanalyzing this somewhat and Jade may be fantastic, but I liked how simple this was.

You can find the resulting code from this experiment on my GitHub Repository.