Dev Diary S01E03: Building the first Angular page


Introduction

In my previous post, Dev Diary S01E02, I explained the configuration of my environment for the client side. If you remember, I am building this application with Visual Studio Code and will also be building the server side component using Visual Studio 2015.

To be honest, I got impatient when developing this and decided that I would start to get to grips with the Angular part. I didn’t really understand things entirely but built my first page index.html.

 

Angular ng-app, ng-view and controllers

The Angular App Homepage (index.html)

So to get things running, I needed to reference the necessary components so that I could start to use them.

Angular is a JavaScript based Model View View Model based application framework which is used to build client side SPAs or Single Page Applications. We need a single page which is going to host the application. This is going to be our homepage, index.html.

Index.html had the following references added to load the Angular, jQuery, Bootstrap components. I added these under the closing tag as this allows the browser to load the page more quickly.


/bower_components/angular-route/angular-route.js
/bower_components/angular-resource/angular-resource.js
/bower_components/jquery/dist/jquery.js
/bower_components/bootstrap/dist/js/bootstrap.js

The other thing is that we need to tell Angular about the fact that this is an app and also tell it when to render the view.

Below is the index.html file

 

<!doctype html>
<html lang="en" ng-app="itspInvoiceFormApp">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>iThink SharePoint Invoice System</title>
<link rel="stylesheet" type="text/css" href="/bower_components/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" type="text/css" href="/app/css/invoiceformapp.css" />
</head>
<body>
<div ng-view></div>
</body>
<script src="/bower_components/angular/angular.js"></script>
<script src="/bower_components/angular-route/angular-route.js"></script>
<script src="/bower_components/angular-resource/angular-resource.js"></script>
<script src="/bower_components/jquery/dist/jquery.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="/app/controllers/invoiceControllers.js"></script>
<script src="/app/app.js"></script>
</html>
view raw index.html hosted with ❤ by GitHub

So you can see we have line #2 which an Angular directive, ng-app, which I will talk about a little later. This tells Angular that the application that will be loaded on this page is called itspInvoiceFormApp.

We have all the links to the scripts mentioned above and also the applications CSS for bootstrap.css and the application, invoiceformapp.css.

In the <body> tag, another Angular directive is added to a <div> tag. This is ng-view. This tells Angular where to render our view and provides the entry point for switching the content in our Single Page Application.

So now we have our index.html done lets move on to some JavaScript!

 

The Angular App Code (app.js)

Next, the Angular app was configured in /app/app.js. I had a look through the various examples on the Angular.js website and also out there via Bingle.

I added the following to app.js

 

'use strict';
var invoiceFormApp = angular.module('itspInvoiceFormApp',
[
'ngRoute', 'invoiceControllersModule'
]);
var appStart = function($routeProvider) {
$routeProvider.when('/invoices', {
templateUrl:'/app/views/list-invoices.html',
controller: 'listInvoicesController'
}).otherwise({
redirectTo: '/invoices'
});
};
invoiceFormApp.config(['$routeProvider', appStart]);
view raw app.js hosted with ❤ by GitHub

 

So lets talk through this, the first line #1 is telling JavaScript to run in strict mode. This helps check for errors in the JavaScript, more information can be found here:

Line 3, creates a variable called invoiceFormApp using the angular.module() function. We pass in the name of the module, in this case ‘itspInvoiceFormApp’. The next parameter in the square brackets are the dependencies that the application relies on. This is important, Angular has this dependency injection engine, which we can take advantage of. In this case we are dependent on the Angular routing module, called ngRoute.

Next, I had to to configure the application, so create a function which provides the configuration of the app. From my limited experience, I know that this is going to change quite a bit as we start loading in more dependencies.

So the function currently has one parameter, this will increase as the number of dependencies get added to the application. The configurationProvider function has one parameter which maps to the invoiceFormApp.config() which is passing in the objects in the [‘$routeProvider’] into the function. So if we had the following [‘$routeProvider’, ‘myOtherThing’], then we would update the function assigned to configurationProvider to:

var configurationProvider=function($routeProvider,$myOtherThing).

 

Angular Routing

Anyway, I hope that helps clear that function up a bit, it took me a bit of time to get the hang of it. So within my app, I used the $routeProvider to create a route for ‘/invoices’. Now, when you setup a route you need to provide a couple of additional bits of information.

  • templateUrl: ‘[server relative url to the html file that is going to hold the view’
  • controller: ‘[name of the controller that will handle setting up the view]’

I setup the /invoice route to go to a view located at ‘/app/views/list-invoices.html’ and to use a controller named ‘listInvoicesController’. Notice the final call to .otherwise() on the $routeprovider variable this will cause the application to default to this route and page if there is no match found for the user’s input or the user is directed by the application to an invalid endpoint..

Now we have our routes setup, I had to give them something to point to.

 

Views and Controllers(View Model)

With the default route created,  next I had to create a view and a controller to implement the route.

 

View

Lets start with the view first, I created a view in VS Code called “list-invoices.html” in the /app/views folder.

Finally, we are getting to try out Angular. This page is being used just to view the data.

This is what I ended up putting together for list-invoices.html.

 

<div class="container">
<div class="row">
<div ng-show="showInvoiceList" class="col-md-10 col-sd-3">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<th>Date</th>
<th>Invoice Reference</th>
<th>Company Name</th>
<th>Total</th>
<th>Status</th>
</thead>
<tbody>
<tr class="clickable-row" ng-repeat="invoice in invoices">
<td>{{invoice.invoiceDate}}</td>
<td>{{invoice.reference}}</td>
<td>{{invoice.companyName}}</td>
<td>{{invoice.currencyType}}{{invoice.invoiceTotal}}</td>
<td>{{invoice.status}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="row">
<div ng-show="error !== ''" class="col-sd-3">
Current Error: {{error}}
</div>
</div>
</div>

 

So basically I have a table wrapped up in some <divs> the outer <div> has the class name container, this is a bootstrap thing to demark the content that is to be styled by bootstrap, the inner div with the class name row creates a new row.

Now on to the actual Angular stuff. we have these various tags starting with “ng-“, these are called directives and allow you to do something with the data that you have bound to the page from your controller and data, or model.

The example that we can see is ng-show   (ine 5) this points to something in or model which evaluates to a boolean value and will display that <div> element when it evaluates to true.

I think this is pretty cool stuff, I was always amazed when I saw this kind of thing with Knockout.js

Anyway, so next we render our data, so we have a table which has been tagged with various bootstrap classes to make it responsive. At some point I am sure I will have to work out the responsive stuff works. The cool bit with the table, starts at row 16.

We have a line which reads <tr class=”clickable-row” ng-repeat=”invoice in invoices”>. So this Angular directive ng-repeat allows us to loop through an array of objects which are in an array called invoices.

This <tr> element block will get repeated for each invoice in invoices, within the <tr> we have a number of <td> elements which are being used to display the values in the properies found on the invoice  object. This is one way that Angular does its data-binding. So using {{invoice.invoiceDate}} we can display the contents within the invoice object.

The rest of the page is pretty uninteresting, I did also add a section to display errors which is quite neat and shows another thing that you can do with Angular directives which is actually add logic within the directive. So we have a <div> tag which has the ng-show  directive set to ng-show=”error!==’’”. So if there is an error in our data model then this div will show the error.

Anyway, so until I show you the controller, it does not really make sense as how do we know what data we are binding to the view?

 

Controller and Model

In order for the view to work we need to create a controller and also the model that the controller is going to pass into the view.

I created a file called invoiceControllers.js in the /app/controllers folder.

Within this file, I created a new module which created a module called InvoiceControllerModule. Then we registered a factory called invoiceController. I have to say that I now know that this was a mistake. But at the time I didn’t realise it. I will talk about the changes that I made in a later blog post.

Anyway, now that we have the factory we need to create a function which is called when the factory is initialised.

 

invoiceControllersModule.factory('listInvoicesController', ['$scope', function ($scope) {
$scope.invoices = [];
$scope.error="";
]

 

Note that the factory method takes a function and the parameters match the attributes defined in []. This controller is taking just a $scope variable.

Actually the $scope variable is very important and represents the view model which can be referenced within your (.html) view file.

We created a couple of properties of the $scope object to hold an error and also to hold a list of invoices.

Next, we need to add some invoices to the array, so that we have something to display.

To keep things easy I just created a load() method on the $scope object to load the data.

This now creates a controller which exposes a $scope variable, final file looks like this.

 

'use strict'
var invoiceControllersModule = angular.module('invoiceControllersModule', []);
invoiceControllersModule.controller('listInvoicesController', ['$scope', function ($scope) {
$scope.invoices = [];
$scope.error="";
$scope.showInvoiceList=function(){
return true;
};
$scope.load = function(){
var invoice=createInvoice();
invoice.reference="INV01";
invoice.companyName="Contoso";
invoice.agencyContact="Jack Black";
invoice.vatRate=20;
invoice.invoiceTotal=10000;
$scope.invoices.push(invoice);
invoice=createInvoice();
invoice.reference="INV02";
invoice.companyName="Fabrikam";
invoice.agencyContact="Jack Black";
invoice.vatRate=20;
invoice.invoiceTotal=10000;
$scope.invoices.push(invoice);
};
$scope.load();
function createInvoice(){
var invoiceObject={
reference: '',
companyName: '',
invoiceDate: '',
contact:'',
addressLine1:'',
addressLine2:'',
addressLine3:'',
addressLine4:'',
addressCity:'',
addressCounty:'',
addressPostCode:'',
addressCountry:'',
agencyName:'',
agencyContact: '',
invoiceLines: [
],
invoiceTotal:0,
currencyType:'£',
vatRate:0,
vatAmount:0,
invoiceTotalWithVat:0,
status:'',
createdBy:'',
modifiedBy:'',
created:'',
modified:'',
};
return invoiceObject;
};
}]);
'use strict'
var invoiceControllersModule = angular.module('invoiceControllersModule', []);
invoiceControllersModule.controller('listInvoicesController', ['$scope', function ($scope) {
$scope.invoices = [];
$scope.error="";
$scope.showInvoiceList=function(){
return true;
};
$scope.load = function(){
var invoice=createInvoice();
invoice.reference="INV01";
invoice.companyName="Contoso";
invoice.agencyContact="Jack Black";
invoice.vatRate=20;
invoice.invoiceTotal=10000;
$scope.invoices.push(invoice);
invoice=createInvoice();
invoice.reference="INV02";
invoice.companyName="Fabrikam";
invoice.agencyContact="Jack Black";
invoice.vatRate=20;
invoice.invoiceTotal=10000;
$scope.invoices.push(invoice);
};
$scope.load();
function createInvoice(){
var invoiceObject={
reference: '',
companyName: '',
invoiceDate: '',
contact:'',
addressLine1:'',
addressLine2:'',
addressLine3:'',
addressLine4:'',
addressCity:'',
addressCounty:'',
addressPostCode:'',
addressCountry:'',
agencyName:'',
agencyContact: '',
invoiceLines: [
],
invoiceTotal:0,
currencyType:'£',
vatRate:0,
vatAmount:0,
invoiceTotalWithVat:0,
status:'',
createdBy:'',
modifiedBy:'',
created:'',
modified:'',
};
return invoiceObject;
};
}]);

Now, that this is all put together it generates a page which looks a little like this.

image

 

Make sure that if you are loading some data n your controller with a load() function, that you call it. I spent a couple of minutes, wondering why I did not have any data loaded and the realised I hadn’t actually called the function.

 

When testing and debugging use http://localhost over http://127.0.0.1

Something that I noticed with Google Chrome when testing the environment is that the css would not work correctly if I tested using http://127.0.0.1:8080 so I ended up using http://localhost:8080 which caused the styling to render correctly.

 

Next Episode

I hope you found this useful, please let me know if there is something that needs more clarity.

I have moved this code into GitHub and it is currently available here:

https://github.com/ithinksharepoint/IT365.InvoiceFormApp.Client/tree/master

In the next episode we are going to put together some add functionality and also configure the application navigation.

Dev Diary S01E02: Angular / WebAPI / Azure Document Db App – Client Environment Setup


Introduction

In my previous post: Dev Diary Entry 1: Azure Web App with MVC WebAPI, Angular and Azure DocumentDb, I introduced the Invoice Management App that I am planning to build.

For complete transparency, the application that I am talking about building has been in development for a week or so now. So, as I write this I am playing catch up. I have been writing down all the problems that I have had and how I resolved them. My aim is that we will quickly get up to date so that I am coding and then I can quickly write about what I did.

Today, we are talking about setting up Visual Studio Code and Visual Studio 2015 to host my applications. Remember we are building two components, the Angular client application in Visual Studio Code and the MVC Web API component using Visual Studio.

 

Setting up the Environment

Visual Studio Code

Developing in Visual Studio Code is quite different to using Visual Studio, the team at Microsoft are doing a great job at improving the application but it does feel very unfamiliar to me who has been using Visual Studio for a rather long time.

Anyway, I downloaded VS Code from http://code.visualstudio.com/ and installed it on my machine.

I am developing on a Surface Pro 4 with Windows 10 x64. So the instructions provided are for Windows but it is pretty similar for MAC OSX and Linux.

 

Developer Directories

I am developing in the c:\dev folder and have created a subfolder called ITSP and then a subfolder, VSTS. The final directory is c:\dev\itsp\vsts

 

Node and NPM

The next step, was setting up the environment, I had spoken to a few people and read a few posts and the way to go with VS Code was using Node.js tooling and the Node Package Manager, npm.

Node provides a few lightweight services which we can take advantage of when developing. The one that I make most of is the built in HTTP server, but more on that later.

NPM or Node Package Manager provides a fantastic way of downloading, installing and keeping your dependencies up to date. I guess the name came from Redhat’s Package Manager or RPM. To be fair it is also like NuGet which the .NET world have been using to keep their dependencies in check.

So I downloaded and installed Node from https://nodejs.org/en/ and choose the latest build which was v5.6.0, I see that version v6 is out as I write this. The download is an MSI so was a quick simple install.

Next is NPM, so actually NPM comes included with Node.js but I wanted to make sure that I had the latest version of NPM. This is the advice in the NPM Installation instrucitons found here: https://docs.npmjs.com/getting-started/installing-node

So to do that I started the Node,js command prompt

  • npm install npm –g

The command calls npm telling it to install a package called npm with –g which means to install it so it is available globally.

 

Bower

The other tool that seems to be great at dependency management is Bower. Now, I had a hard time working out what the difference was between Bower and NPM. Why do I need both. Well Bower seems to be better at installing and configuring the client side components and NPM for the server side components.

One of the reasons that I have chosen Bower is to be honest a lot of tutorials use it. Now, this is something that I will look into a little later on the project but I want to get up and running. There do seem to be a lot of alternatives such as Browserify and Webpack.

 

Angular

So this is my first project using Angular, I hear people talking about it all the time! As I was researching into the product more it became embarrassing to see how long its been out before I have had a go at using it!

One of the chaps speaking about this stuff from the SharePoint world is Andrew Connell via his blog. He has a great amount of content which I found really useful.

As I mentioned in my previous post, I have been reading up on Angular via their documentation pages. I also have been listening to Scott Allen’s AngularJS: Getting Started on Pluralsight.

 

Bootstrap

As a developer, I need help with design so I have decided to use Twitter Bootstrap and fortunately this is quite easy to include in your project.

I am sure that you have used Bootstrap more than me!

However, Bootstrap is a framework which provides a grid based system for defining responsive designs based on having different css classes for different screen sizes.

I have to say I am always amazed what front-end developers can do with Bootstrap, I am sure in time that it will become second nature.

 

Yeoman

Yeoman is like File->New Project in Visual Studio. It is pretty cool actually and allows you to create or use pre existing templates to make the project scaffolding. I did look at this and various templates but I found them complex and they started to pull in a lot of stuff which I did not know about.

So to kept it simple, I haven’t used Yeoman as I wanted to learn how to build the project from scratch rather than have a tool do everything for me and I then don’t understand my dependencies.

I am sure that I will change my behaviour next time once I understand how everything fits together.

Adal.JS

Now I know that I am going to be using Azure Active Directory as my authentication and authorisation mechanism.

ADAL is a library that has been created which provides a wrapper to manage authentication with Azure AD. The library is superb and really straight forward to use for the .NET stack. Fortunately, there is also a JavaScript implementation called Adal.js and even better there is a module created for Angular!

I have been following Adal for a while and the go to guy is Vittorio Bertocci, he has some great posts on all things ADAL.

Introducing ADAL JS v1

The article is great and talks about how to install the framework using Bower and then provides examples including one for authenticating your application with Angular!

 

jQuery

Of course we need jQuery, I don’t think this framework needs any introduction.

This was installed from the node.js command line:

  •  using bower install jquery

 

 

 

Creating the Client Side Visual Studio Code Project

Ok so now I have talked about all the bits and pieces that I am using for the client side of the application, I will try and explain the steps that I took to create the project for Visual Studio Code.

Remember we have two components in this application:-

  • Angular Client side application being developed in Visual Studio Code
  • MVC WebAPI Server side application being developed in Visual Studio 2015

So,  to create the Visual Studio Code project you need to create a package.json file. This is the equivalent of a Visual Studio csproj file for Visual Studio C# Projects. It contains the version number, name of the project, description and also it has scripts section where you can define commands to perform actions when developing your application.

So to get started I did the following:-

  • started node.js command prompt
  • created a directory c:\dev\itsp\vsts\IT365.InvoiceApp.Client
  • from the directory just created I ran npm init
  • this wil start a wizard which then asks for various information about the project including its name, description and author details

Now that we have our package.json created we can fire up Visual Studio Code

  • code .

This will start Visual Studio Code in the current directory which will cause Visual Studio code to read the application information created so far.

 

Install Dependencies

Now we have the project created next it is time to bring in our dependencies.

We will use npm and bower to pull in the dependencies:-

  • bower install bower-angular
  • This will install the Angular component into our project into a folder called bower_components\angular
  • Angular Route
  • bower install bower-angular-route
  • This will allow us to define our routes in the application so that we can control where the user goes, what they see and which controller to use. More on this later
  • Angular Mocks
  • bower install bower-angular-mocks
  • This will allow us to do Test Driven Development when we start looking at Continuous Integration and Continuous Delivery
  • Angular Sanitizer
  • bower install bower-angular-sanitizer
  • This helps us to strip out dangerous characters from when parsing HTML

 

  • Bootstrap
  • bower install bootstrap
  • This will give us a better look and feel than I could do!

So, we have the Angular and Bootstrap stuff installed that I thought we needed.

 

Next we need to install the ADAL JS stuff

  • ADAL JS
  • bower install angular-adal
  • This will allow us to manage the login / authentication, authorisation process in our application with Azure Active Directory

Then we have jQuery

  • bower install jquery

 

Finally, I want to be able to actually run the application locally and a really nice way of doing that is using the Node.js HTTP Web Server, http-server

  • Node http-server
  • npm http-server –g
  • This will install the http server globally so we can use it in our next applications

 

Create Application Structure

Next I created the application structure

So the following directories and files  were created from within Visual Studio Code

  • [app]
  • [controllers] – this will hold all our controllers
  • [services] – this will hold all our services
  • [entities] – this will hold our JavaScript objects relating to entities such as Invoices, Users etc
  • [views] – this will hold all our views
  • [css] – this will hold our CSS styles
  • [images] – this will hold our image
  • app.js
  • index.html

I am sure that I will be adding more folders etc but that gave me something to start with.

 

Trying out the Application quickly

So one of the tips that I picked up from the node.js documentation was how you can create tasks with NPM.

I was a little confused by this to be honest but after a bit of investigation I found out that I could modify the package.json to configure these tasks for NPM to be able to use.

  • Opening up package.json, i found the scripts section and added the following
  • When i first did this i added just the http server –a 127.0.0.1 –p 8080
  • however, after more reading I realised I could run multiple commands using the && syntax
  • So we ended up with

npm-start-task-config

 

Now this is pretty cool, from the node.js command prompt I can type

  • npm start

This will start a web server and fire up the browser taking me to the homepage!

image

 

Next Episode

So in the next episode, we will actually start develop something. I was pretty excited to try out Angular so I just started to build the application using client side data. So we will cover that.

I hope you can join me for the next episode.