Angular learning experiences

As part of the Conference App that we built recently I was tasked with learning how to use Angular.

This blog details some of the ups and downs of the learning experience.

All code referred to in this blog post is available on GitHub: https://github.com/Creou/ConferenceApp

Disclaimer

Having now finished the first phase of the conference app I at least know something about Angular, although I'm still far from an expert. Undoubted some of the ways that I have accomplished goals could have been done better, but this is part of the learning experience.

This is not a 'learn Angular' blog, it's a blog about me trying to learn Angular.

Prior Knowledge

I've previously worked on WebAPI projects so I was familiar with producing a REST back end. I've also worked on ASP.net and WebForms projects and felt the pain of trying to understand the .Net page lifecycle and custom controls.

I've not done a great deal of HTML or Javascript as most of the projects I'd previously worked on had already existing front end systems in place and had never worked on a single page web application.

Why

Most of my previous experience has been with server side technologies with only minimal front end experience and so I'm pushing myself to keep up to date with newer and emerging front end technologies. Simon had identified a need for an app to assist conference delegates, therefore this seemed like a good excuse to get stuck into learning about a single page app framework.

Why Angular

There are a number of single page app frameworks that we could have chosen like Ember, or Backbone (a comparison of which can be found here:  https://www.airpair.com/js/javascript-framework-comparison)

As a company we've recently been exposed to (the results of) Angular on a client project and we were suitably impressed. Also it seems like one of the most popular frameworks and possibly the most supported so we choose this as our framework of choice for this app.

Conference App

The point of the app is to facilitate the experience of attending a conference with multiple 'Tracks' of discourses that could be attended. A user can view the various sessions grouped by either 'Track' or by time and be presented with list of session titles and times. By clicking on those titles they can find out additional information such as room name/number, the speaker, and the session description. The user can also choose to leave feedback about each session and also about the conference as a whole. This feedback comprises some 1-5 star ratings for various aspects and also free text for suggestions/comments. The feedback is saved to a database for the conference organisers to analyse to improve future events.

If you want to see the finished app you can find it here: http://creouconferenceappserver.azurewebsites.net/app/AwesomeApp.html#/home

Initial impression.

Having previously worked with ASP.net web forms I was excited about the (relative/reported) simplicity of the Angular way. Had I had experience of some of the other SPA frameworks this may not have been such a novelty, but this was the first one I'd had opportunity to use/learn. (If you've ever done web forms you will understand).

I was developing the app in Visual Studio and being a fan of Nuget used that to obtain the Angular package. There are some fairly easy to follow videos on the Angular web site, although it wasn't clear from the outset how these simple demos would translate to the requirements of my app.

This is partially due to it being a web technology but I found it initially confusing that there seems to be a fairly large number of different ways to achieve the same result without any being obviously more correct than others. I also think the Angular website needs some love to make it more obvious where the tutorials are.  (They are in the 'Develop' toolbar menu). I ended up watching 3rd party tutorial videos which may or may not have contributed to the 'many ways to do something' issue.

Angular Philosophies

Angular code is modular with all dependencies injected via constructor injection. This makes it very easy to write automated tests for.

app.controller('controllerName', function (injected, dependancies, here) {
...code that uses the dependancies...
});

Structure

The 'single page' is constructed in the usual way, either as a static page or delivered some other way if required (MVC). The single page has a single 'ng-app' attribute on the html tag that signifies that this is an angular container. Also on the static page there is an element with an 'ng-view' attribute. This signifies the container for all of the Angular generated content. Additional content can appear outside of this but will not be inserted by Angular.

<html lang="en" ng-app="app">
<head>...</head>
<body>
	...
	<div id="view" ng-view></div>		
</body>	
</html>

Routing

Navigation between 'virtual' pages is via anchor style links which are 'routed' via a routing engine to specified 'controllers' and 'templates'.

app.config(function ($routeProvider, $locationProvider) {
	...
	$routeProvider.when('/byTrack', {
		templateUrl: 'partials/byTrack.html',
		controller: 'ByTrackController'
	});
	$routeProvider.when('/byTime', {
		templateUrl: 'partials/byTime.html',
		controller: 'ByTimeController'
	});
	...
}

The routing can load templates via HTTP requests from separate files reducing the amount of mark-up that must be loaded on app start-up/page load. 'Templates' are basically the 'view' of MVVM and are Angular compiled HTML files that will get inserted into the ng-view container.

Links do not have to be within the ng-view container as demonstrated in the conference app by a Bootstrap navbar that sits just above the ng-view container.

<div role="navigation">
	<ul class="nav nav-pills ddd" nav-active-link>
		<li role="presentation"><a href="#/home">Home</a></li>
		<li role="presentation"><a href="#/byTrack">By Track</a></li>
		<li role="presentation"><a href="#/byTime">By Time</a></li>
		<li role="presentation"><a href="#/eventFeedback">Feedback</a></li>
	</ul>
</div>

Controllers and views

Controllers, like other angular components are just JavaScript functions. The controller prepares data making it available for binding to the view (equivalent to the view-model?). In our conference app the controllers' job is typically to make a request from the data layer, and then sort/filter the data as required. It is also where event listeners are registered to deal with e.g. button clicks and then sending the data back to the data layer.
In the example below from the conference app the event feed-back controller is fetching the 'company size' values

app.controller('EventFeedbackController', function ($scope, ...) {
	...
	$scope.statii = statiiService.query(function (value) {
		var x = value;
	});...
}

Which are used to populate a drop down combo box bound in the view:

								
<label class="col-xs-7 col-sm-8">What size company do you work for?</label>
<div class="col-xs-5 col-sm-4">
<select ng-model="feedback.CompanySize" class="form-control" ng-disabled="formDisable" ng-options="size.Id as size.Text for size in sizes">
	<option value="">Select company size</option>
</select>
</div>

Directives

Directives are like code snippets, or partial views. They can have their own controller and template. They are also the only part of the Angular framework where it is recommended to interact directly with the DOM. In the conference app I used a directive to render the sessions in a consistent way and to minimise code duplication as various pages needed to render session information. They can also be used to modify elements rather than replace them. IMHO directives are one of the more complicated bits of Angular with a lot of things, some quite complicated, to understand. However some of the more simple things can be picked up fairly quickly.

Session detail directive from app:

		
app.directive('sessionDetail', function () {
	return {
		templateUrl: 'partials/sessionDetail.html',
		restrict: 'E',
		replace: true,
		scope: {
			session: '=data'
		},
		controller: 'SessionDetailController'
	};
});

Issues

Some things can be quite trying, for instance directives are supposed to be declared using pascalCase but consumed in hyphenated-format. E.g. my session directive was declared as sessionDetail but had to be consumed as session-detail. It's a feature that you can do this however I didn't realise at first that it was required. You cannot consume your directives in their declared pascalCase, it just doesn't work. There is actually a page on the Angular site that lists some common pitfalls, but personally I think these will depend on your programming background. I also had issues with 'promises'. This is possibly due to the various 'types' of promises that exist currently due to non-universal browser support, but either way promises didn't seem to work as expected in a consistent manner which meant I ended up using call backs some of the time.

Awesomeness

It's incredibly easy to knock up a CRUD style application in minutes once you've got the hang of it with virtually no 'boilerplate'.
Example on SitePoint.

Conclusion

Would I be happy to use Angular again? Yes most definitely. Even when you consider technologies like MVC which make CRUD style operations easy, if you are going to use Ajax or Javascript at all in your pages then it could potentially benefit from Angular.

http://www.codeproject.com/Articles/808213/Developing-a-Large-Scale-Application-with-a-Single

Sam Price

Unless otherwise specified all code in this post is made available under the MIT license. Copyright 2015 Creou Limited.