Single Page Applications

With an Introduction to Angular JS

wayne.maurer@lambda-it.ch

The evolution of the Web

Static Pages

(boring)

Static Pages

CGI Scripts

Microsoft
Active Server
Pages

PHP

My first AJAX application

Reason 1: Slow network

Reason 2: Slow server

Multi-level report

Fetch detail data with XMLHTTP

Convert to HTML with XSLT

Use JavaScript to insert into DOM

Internet Explorer only

Application code delivered once to client. AJAX data transfers as required

Year 2002 ...

ASP.NET Web Forms

Attractive for developers coming from desktop development

Leaky abstraction layer that doesn't truly capture the Web paradigm

JSF - Java Server Faces

JSF was created to be used in scenarios where an enterprise backend already existed built in Java/XML, and a need existed to reuse that same team of enterprise developers to build also the frontend

Abstracts away HTML, CSS and HTTP

Attempts to create statefulness on top of the stateless HTTP protocol

ASP.NET MVC

Takes a more 'architectural' view of web application development

MVC supports a clean separation of concerns

A more HTML/CSS/JavaScript and HTTP centric model of producing web pages

Ruby on Rails is based on similar concepts

GWT - Google Web Toolkit

Moves MVC to the client

Web page is viewed from an object-oriented point of view

The notion of document and elements is hidden away by the framework

Client-Side Technologies

Java Applets

Adobe Flash

Microsoft Silverlight

JavaScript

JavaScript is to Java as hamster is to ham, as carpet is to car, and as irony is to iron.

- h/t @shanselman

JavaScript is the Wild West of programming. Unfortunately, that makes it similarly ripe for fly-by-night quacks peddling snake oil.

- h/t @tomdale

JavaScript

The World's Most Misunderstood Programming Language

Nothing to do with Java

The -Script suffix suggests that it is not a real programming language

Lisp in C's Clothing

Perception: the language of Script Kiddies?

Good Parts and Bad Parts

jQuery

A library for simplifying HTML document traversal and manipulation, event handling, animation, and Ajax

Server-Side MVC + jQuery

REQUIRES DISCIPLINE

Server-Side MVC + jQuery

CAN BE
AN AWFUL MESS

What is a Single-Page Application?

SPA Architecture

'Thick' Web Client + HTTP Server API

The Backend

Normally a RESTful Web Service with JSON formatted data

Rather slim in comparison to server-based MVC frameworks

Technology independent. Choose your flavour: Node.js, .NET, Java

Promotes an architectural Separation Of Concerns

Introducing AngularJS

The story behind Angular

Built by full-time Java GWT developers at Google

Created as a response to how they felt that Java frameworks limited their frontend development productivity

Angular Vocabulary

Model, View, View Model, Data Binding, Dependency Injection, AJAX, Module, Scope, Controller, Service, Factory, Directive, Filter, Routing, Promise

Model, View, Whatever

The Angular JS take on MVC or MVVM

Decouple the Model from the View, and loosely glue the two together with a Controller

The Model

A POJO (Plain Old Javascript Object)

	var contact = {
		firstName: 'Miško',
		lastName: 'Hevery',
		twitterHandle: 'mhevery'
	};

Can be a View specific model or a DTO, not necessarily a Domain Model

The View

Simply HTML annotated with attributes (directives) and a special expression language

	<span ng-bind='contact.twitterHandle'></span>
	<span>{{contact.twitterHandle}}</span>
	 
	<input type='text' ng-model='contact.firstName'>

The directives enable data binding (Observable Pattern) between the View and the Model

The Controller

Where we interact with the View and the Model

Where presentational logic can take place to keep the UI bindings in sync with the Model

A meeting place between business logic and presentational logic

Not the correct place for interacting with the DOM

Example Controller

	angular.module('Calculator', [])
		.controller('CalculatorCtrl', function ($scope) {
			$scope.model = {
				left: 6, right: 7
			};
			$scope.multiply = function () {
				return $scope.model.left * $scope.model.right;
			}
		});

Example View

	<div ng-app='Calculator' ng-controller='CalculatorCtrl'>
		<h3>Interactive Calculator</h3>
		<input type='text' ng-model='model.left'>
		*
		<input type='text' ng-model='model.right'>
		=
		<span ng-bind="multiply()"></span>
	</div>

A Running Example

Interactive Calculator

* =

Directives

Markers on a DOM element with attached behaviour

Allow you to extend HTML

Allow you to componentise HTML

Where you manipulate the DOM and catch DOM events

Core Directives

Angular's built-in directives

ng-bind: replaces text content of HTML element

ng-model: bindsinput,select,textarea to a property on the scope

ng-class: set CSS classes on a HTML element

ng-repeat,ng-click,ng-href,ng-show,ng-hide,ng-if,ng-switch,ng-view and many more ...

Custom Directive Template

/templates/attendeeEntry.html

	{{attendee.firstName}} &nbsp; {{attendee.lastName}}
	<a ng-href='https://twitter.com/{{attendee.twitterHandle}}'>
		@{{attendee.twitterHandle}}
	</a>
	<button class='remove-btn'></button>

Custom Directive Code

	app.directive('attendeeEntry', function () {
		return {
			scope: { attendee: '=', remove: '&' },
			templateUrl: '/templates/attendeeEntry.html',
			link: function (scope, element, attrs) {
				element.find('button').on('click', function () {
					scope.remove();
				});
			}
		}
	});

Using the Directive

	<div ng-controller='AttendeeCtrl'>
		<input ng-model='newAttendee.firstName'>
		<input ng-model='newAttendee.lastName'>
		<input ng-model='newAttendee.twitterHandle'>
		<button ng-click='add()' ng-disabled='!isNewAttendeeValid()'> Add Attendee
		<ul>
			<li ng-repeat='attendee in attendees'>
				<attendee-entry remove='removeAttendee($index)' attendee='attendee'>

Attendee List Controller

	$scope.attendees = [];
	$scope.newAttendee = createNewAttendee();
	$scope.isNewAttendeeValid = function () {
		return $scope.newAttendee.firstName && $scope.newAttendee.lastName
			&& $scope.newAttendee.twitterHandle;
	};
	$scope.add = function () {
		$scope.attendees.push($scope.newAttendee);
	};
	$scope.removeAttendee = function (index) {
		$scope.attendees.splice(index, 1);
	};

Attendee List Running Example




¡ Time Out !

Services

View independent business logic

Organise and share functionality across your app

Supports your standard best practice:
Don't Repeat Yourself (DRY)

Services are singletons

Angular Services: $http and $resource

$http facilitates communication with remote HTTP servers

$resource is a higher level service for communication with a RESTful data source

Provides additional support, e.g. caching

Dependency Injection

A software design pattern that deals with how components get hold of their dependencies

Removes the responsibility of locating the dependency from the component

Especially useful in automated testing, allowing us to mock external dependencies, and focus our testing on units

Angular Dependency Injection

Defining dependencies:

	app.controller('LoginCtrl',
		function ($scope, $location, loginService) { }
	);

Registering Services:

	app.service('loginService', function() {});

Routing

In a Web Application, the URL is a representation of the application's state

Single-Page Applications use hash routing

http://inov-8.com/#/en/shoes/trailroc/255

Angular's router is a module which can be replaced

Angular's Route Provider

	$routeProvider
		.when('/:language/shoes', {
			templateUrl: 'views/shoes.html',
			controller: 'ShoeListCtrl'
		})
		.when('/:language/shoes/:model/:number', {
			templateUrl: 'views/shoe.html',
			controller: 'ShoeCtrl'
		app.controller('ShoeCtrl', function ($scope, $routeParams) {
			var language = $routeParams.language;

Testing

Unit Testing: is a unit of source code fit for use?

ngMock provides support to inject and mock Angular services into unit tests

Karma: Google's test runner with adaptors for Jasmine, Mocha and QUnit

$httpBackend: fake HTTP backend implementation suitable for end-to-end testing or backend-less development

When do you know that you're doing something wrong?

You're writing jQuery in your controller

You're asking yourself 'how do I have directive A communicate with directive B'

You have “War and Peace” controllers

You have a “Directive of Doom”

When do you know that you're doing it right?

Ask yourself:

“Is this Good Software?”

Are you applying the best practices you apply in other software projects?

Does it have separation of concerns; good encapsulation?

Is it easy to test?

Can you modify small features without large code changes?

Development Challenges

Many developers are not competent JavaScript developers

Can be helped with a higher level language such as TypeScript

New tools and technologies

Authorisation & Authentication, SEO

Other SPA Frameworks

Backbone.js - minimal set of data-structuring and user interface primitives

Knockoutjs - standalone JavaScript implementation of the Model-View-ViewModel pattern with templates

Ember.js - an opinionated framework for creating ambitions web applications

Meteor - full stack (client and server-side) web application framework

Angular - amongst other strengths, the most used

Current Angular Versions

1.2 - Old stable version that works still works with older (IE8) browsers

1.3 - Current version, no support for IE8. Performance enhancements

Angular v2.0

Design not finalised yet

Key Concepts: Mobile First, Loosely Coupled Modules, Simplicity, Metadata and Performance

Built for the browsers of the future: only Evergreen browsers will be supported

Announcement of a new JavaScript superset language: AtScript

Migration from 1.3 looks to require significant work

Are Single-Page Applications suitable for every application and web site?

What are SPAs best for?

Modern web applications - line of business applications with logic

Dynamic web pages

Responsive web applications in combination with
UI framework (e.g. Bootstrap, Foundation)

Offline-capable Web Applications
(e.g. Chrome Apps)

What are SPAs not the best for?

Intensive Mobile Apps embedded in Cordova/Phonegap

Static or Content only web sites

Microsites and landing pages

Thank-you for listening

Questions are Welcome

This is only
the End of the Beginning ...

Enjoy! ;-)

wayne.maurer@lambda-it.ch
@waynemaurer


lambda-it.ch
lambda-it.ch/spa-slides