This is continuation from my original post Journey Into Angular – Part 1
Clean Up
I wanted to clear up a few things that I did from my previous post. I originally pulled in all of the angular libraries from NuGet. I uninstalled all the angular libraries, and then from within NuGet only installed AngularJS.Core, AngularJS.Resource, and AngularJS.Route
I originally placed all my custom scripts within the script folder, but this was getting mixed in with the scripts being pulled in from NuGet.
A convention that I have seen is that people are creating an app folder and then having all their custom scripts within that folder and subfolders. So I followed that convention and moved all my custom scripts to an app folder, and then updated the_Layout.cshtml view to reference the new location.
Row Click
One of the changes I wanted to make, was that clicking anywhere within a row would toggle the employees state to indicate if they where in or out of the office, instead of just relying on the checkbox. So I created simple method of the office controller
$scope.toggleStatus = function (employee) { employee.inOffice = !employee.inOffice; };
To get it working I just needed to slightly alter the div, and added ng-click=”toggleStatus(employee)
<div class="row" ng-repeat="employee in office" ng-click="toggleStatus(employee)">
Api
Now that I have the application was updating correctly, the next step was to create an api call to update the data on the server.
Currently I was recreating the data with every GET call. As I don’t want / need a database, I moved the data creation out into a static.
I created a new repository class, with the corresponding interface definition
public interface IEmployeeRepository { IEnumerable<Employee> Get(); void UpdateEmployee(Employee employee); }
and the actual class
public class EmployeeRepository : IEmployeeRepository { private static readonly ICollection<Employee> Employees = new List<Employee> { 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} }; public IEnumerable<Employee> Get() { return Employees; } public void UpdateEmployee(Employee employee) { var employeeToUpdate = Employees.FirstOrDefault(c => c.Id == employee.Id); if ( employeeToUpdate != null ) employeeToUpdate.InOffice = employee.InOffice; } }
In addition to the Get method, I added a new method on the repository to update the employee information. While passing in the full employee object, I am only updating the single field
With the repository in place, the api needs to be updated to include the repository. I cheated and just created the class on the constructor. In a production system, I would have used a DI container which would have injected in the class, but I didn’t see the need for it with what I am currently doing.
The final change was to put into the POST method to update the employee. The updated controller is
[Route("api/office")] public class OfficeController : ApiController { private readonly IEmployeeRepository _employeeRepository; public OfficeController(IEmployeeRepository employeeRepository) { _employeeRepository = employeeRepository; } public OfficeController() : this(new EmployeeRepository()) { } public IHttpActionResult Get() { var employees = _employeeRepository.Get(); return Ok(employees); } public IHttpActionResult Post(Employee employee) { _employeeRepository.UpdateEmployee(employee); return Ok(); } }
To call the REST method from Angular, update the office-repository class to include a new method with using the angular resources: save
officeModule.factory('officeRepository', function ($resource) { return { get: function () { return $resource('/api/office').query(); }, save: function(employee) { return $resource('/api/office').save(employee); } } });
The new method will call the POST method of the API.
Last step is to then update the office-controller to call the save method. The final office-controller class is
officeModule.controller("officeController", function ($scope, officeRepository) { $scope.office = officeRepository.get(), $scope.toggleStatus = function (employee) { employee.inOffice = !employee.inOffice; officeRepository.save(employee); }; });
With two browsers running, make a change on one browser. Refresh the second browser and the change is displayed correctly.
Still more to be done, as I want to have the second browser updated automatically using SignalR.
As always the code can be found on GitHub.com
Leave a Reply