In the past when I was doing front end development, I was using Knockout. At the time we picked knockout over Angular because Knockout seemed to be the more mature product.
Since that time, it looks like Angular has been adapted for front end development. I say this because searching jobserve for c# web developers most adverts indicate that they want candidates with Angular experience. There may be the occasional job ads that specify Knockout, but that is only as a substitute for Angular. As most ads you apply for, you are dealing with recruiters and hr departments that are mostly non technical and only ever do keyword matching, so if you don’t have the 100% keyword match you are immediately placed on the discarded pile.
So with that in mind I am starting my journey to learn Angular. Although I have been told that Angular is on its way out and that should be using ReactJS instead. But first I will get a better understanding of Angular, and then move onto ReactJS
In / Out of the Office
In the past I used my motordb app, but as this is now a few years old, I am far too lazy to upgrade everything, especially as this app is using Knockout and Typescript, so I have started on a new application to learn Angular.
The In/ Out of Office application is a simple web page to show what members of staff are presently in the office, and which is out of the office. Its not going to win awards, and will never be a production application, but that’s not its purpose.
I wanted the application to list employees at an office, and to display on screen an image of the employee, the employee name, and a checkbox, which if ticked will indicate that the said employee is current in the office.
When an employee arrives they tick their image to indicate that they are in the office, and tick it again when they are about to leave the office.
As I wanted some images to use, I found this vector image.
For names, I used imdb to give me a list actors in Spectre
Getting Started
First things first is to start up a new solution in Visual Studio, and start a new MVC and WebApi application. Think i made a mistake with that, as so many NuGet packages come with the default templates ( and ironically enough one of the NuGet packages installed by default is Knockout )
So I had a look and uninstalled some NuGet packages that won’t be needed, i.e. Knockout, and the webapi help pages.
Initially I am going to be creating this as a mini-spa application. Mini Spa is a term that i heard when watching this Pluralsight video Angular for .NET Developers
Its not a full spa type application because I am still going to be using MVC controllers server side to render the initial page.
As first step I will be bootstrapping the data in from a WebApi, so I created a basic web api controller that will return hard codes data for now.
As always I create a base api controller that will be used by all.
public class BaseApiController : ApiController { }
Now a model
public class Employee { public int Id { get; set; } public string Name { get; set; } public string ImageUrl { get; set; } public bool InOffice { get; set; } }
Simple enough model, id for later use, employee name, Url to their image, and a flag to indicate if they are currently in our out of office. I may decide later to change the bool to an enum but for now a bool is sufficient.
The hard code model
private Employee[] GetEmployees() { return new[] { new Employee {Id = 1, ImageUrl = "/Assets/Images/male01.png", Name = "Daniel Craig", InOffice = false}, new Employee {Id = 2, ImageUrl = "/Assets/Images/male02.png", Name = "Christoph Waltz", InOffice = true}, new Employee {Id = 3, ImageUrl = "/Assets/Images/female01.png", Name = "Léa Seydoux", InOffice = true}, new Employee {Id = 4, ImageUrl = "/Assets/Images/male03.png", Name = "Ralph Fiennes", InOffice = true}, new Employee {Id = 5, ImageUrl = "/Assets/Images/female02.png", Name = "Monica Bellucci", InOffice = true}, new Employee {Id = 6, ImageUrl = "/Assets/Images/male04.png", Name = "Ben Whishaw", InOffice = true}, new Employee {Id = 7, ImageUrl = "/Assets/Images/female03.png", Name = "Naomie Harris", InOffice = true} }; }
And finally the controller to return the data
[Route("api/office")] public class OfficeController : ApiController { public IHttpActionResult Get() { var employees = GetEmployees(); return Ok(employees); } }
Getting Started with Angular
Now time to work on Angular, so I used NuGet to install Angular. I selected AngularJS which seemed to install all the required libaries, but I am sure that with a bit of research I could have discovered what I really needed and then only installed the relevant js files.
I started on the view that the HomeController uses and removed all the html that is included by default in _Home.cshtml and then put in all the Html and Angular code that was required
<div class="jumbotron"> Whos is in who is out </div> <div class="container" ng-cloak> <div class="row"> <div class="col-md-1"> <img ng-src="{{employee.image}}" style="width:50px;height:50px;" /> </div> <div class="col-md-7"> {{employee.name}} </div> <div class="col-md-4"> <input type="checkbox" ng-checked="{{employee.inOffice}}"/> </div> </div> </div>
If you see the img tag, you notice that I don’t have a source attribure, but an ng-src attribute. Because Angular only parses everything after the dom loads, the browser will attempt to load an image named {{employee.imageUrl}}. Ditto with the checkbox, i need to use ng-checked.
The container div has the ng-cloak directive. This directive will stop Angular html template from being briefly displayed by the browser in its raw (uncompiled) form while your application is loading.
The container div also has the ng-controller directive. This tells Angular what controller to use. This will be defined later.
If you had to load the page, all that would be shown is the html and none of the dynamic data. First need to create an officeModule, or else a big fat error. I didn’t try to see what would happen.
var officeModule = angular.module("officeModule", ['ngRoute', 'ngResource'])
I need to include Angular’s ngResource as this is required for ajax queries. I have included ngRoute because later I want to have multiple urls defined within the MiniSpa and ngRoute is required to achieve this
Now that I have defined the module to be used, i now need an Angular Controller. Angular controllers are very different from .net MVC controllers
officeModule.controller("officeController", function ($scope, officeRepository) { $scope.offices = officeRepository.get(); });
I am passing in officeRepository as I am trying to follow the Single Responsibility Principal, as the Controller should not be doing any type of data retrieval.
On the Angular $scope I am defining the global office object that will be used by Angular to bind the data.
Now that I have defined the Angular Controller, I need to create the officeRepository
officeModule.factory('officeRepository', function ($resource) { return { get: function () { return $resource('/api/office').query(); } } });
The $resource returns the ajax promise.
Just need to update _layout.cshtml file to include all the relevant javascript and css files, and run the app, and everything is displayed correctly
Woo Hoo
The source code can be found on Github
[…] This is continuation from my original post Journey Into Angular – Part 1 […]