Introduction

It’s superbowl Sunday and between the snacks it is time to learn something new. Today my eye fell on Angularjs. Angularjs is an MVC framework for javascript. It kinda puts the controllers and model on the clientside and not on the serverside like ASP.Net MVC does. I will use Nancy as our service to provide us with json data.

Server

Our server is pretty simple.

Just make an empty asp.net application and add a Models folder.
Here is my model.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
using System;
 
namespace NancyJTable.Models
{
    public class PlantModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Genus { get; set; }
        public string Species { get; set; }
        public DateTime DateAdded { get; set; }
    }
}
using System;

namespace NancyJTable.Models
{
    public class PlantModel
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Genus { get; set; }
        public string Species { get; set; }
        public DateTime DateAdded { get; set; }
    }
}

And here is my module, which I put in the Modules folder.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
using System;
using System.Collections.Generic;
using System.Linq;
using Nancy;
using NancyJTable.Models;
 
namespace NancyJTable.Modules
{
    public class PlantsModule:NancyModule
    {
        public PlantsModule()
        {
            Get["/plants/{Id}"] = parameters => Response.AsJson(GetPlantModels().SingleOrDefault(x => x.Id == parameters.Id));
            Get["/plants"] = parameters =>
                {
                    return Response.AsJson(GetPlantModels());
                };
        }
 
        private IList<PlantModel> GetPlantModels()
        {
            var plantModels = new List<PlantModel>();
            for (var i = 1; i <= 25; i++)
            {
                var j = i.ToString("000");
                plantModels.Add(new PlantModel()
                {
                    Id = i,
                    Name = "name" + j,
                    Genus = "genus" + j,
                    Species = "Species" + j,
                    DateAdded = DateTime.Now
                });
            }
            return plantModels;
        }
    }
 
}
using System;
using System.Collections.Generic;
using System.Linq;
using Nancy;
using NancyJTable.Models;

namespace NancyJTable.Modules
{
    public class PlantsModule:NancyModule
    {
        public PlantsModule()
        {
            Get["/plants/{Id}"] = parameters => Response.AsJson(GetPlantModels().SingleOrDefault(x => x.Id == parameters.Id));
            Get["/plants"] = parameters =>
                {
                    return Response.AsJson(GetPlantModels());
                };
        }

        private IList<PlantModel> GetPlantModels()
        {
            var plantModels = new List<PlantModel>();
            for (var i = 1; i <= 25; i++)
            {
                var j = i.ToString("000");
                plantModels.Add(new PlantModel()
                {
                    Id = i,
                    Name = "name" + j,
                    Genus = "genus" + j,
                    Species = "Species" + j,
                    DateAdded = DateTime.Now
                });
            }
            return plantModels;
        }
    }

}

Client

First I added another empty ASP.Net web application project to our solution.

I added angularjs to my project. It is on nuget so no problems there.

I want to add a list of plants and I want a details page.

First I need to start with adding my app.j in the js folder. This will take care of the routes.

angular.module('plantsapp', []).
  config(['$routeProvider', function ($routeProvider) {
      $routeProvider.
          when('/plants', { templateUrl: 'partials/plants.html', controller: PlantsController }).
          when('/plants/:Id', { templateUrl: 'partials/plant.html', controller: PlantController }).
          otherwise({ redirectTo: '/plants' });
  }]);

You already see that I have two partial views and 2 controllers.

The controllers are in my controllers.js file.

function PlantsController($scope, $http) {
    $http.get('http://localhost:59025/plants').success(function (data) {
        $scope.plants = data;
    });
}

function PlantController($scope, $routeParams, $http) {
    $http.get('http://localhost:59025/plants/' + $routeParams.Id).success(function (data) {
        $scope.plant = data;
    });
}

So I have a Plantscontroller that uses a get to get my json from my nancy service. And I have a PlantController that uses the routeparameter to tell which plant to get from my service.

See how I inject http and how it magically gets injected for me.

The next thing is to create an index.html which is the base of our views.

HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
 
<html lang="en" ng-app="plantsapp">
<head>
    <title>Plants</title>
    <script src="/Scripts/angular.js"></script>
    <script src="/js/controller.js"></script>
    <script src="/js/app.js"></script>
</head>
<body>
    <div ng-view></div>
</body>
</html>
<!DOCTYPE html>

<html lang="en" ng-app="plantsapp">
<head>
    <title>Plants</title>
    <script src="/Scripts/angular.js"></script>
    <script src="/js/controller.js"></script>
    <script src="/js/app.js"></script>
</head>
<body>
    <div ng-view></div>
</body>
</html>

In the html tag I added an ng-app with the name I provided in my app.js.

I import angular.js, controller.js and app.js.

And I added a div with an ng-view attribute.

Now I need the partials which I put in the partials folder.

HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<table id="table_id">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Genus</th>
        </tr>
    </thead>
    <tbody ng-repeat="plant in plants">
        <tr>
            <td>{{plant.Id}}</td>
            <td><a href="#/plants/{{plant.Id}}">{{plant.Name}}</a></td>
            <td>{{plant.Genus}}</td>
        </tr>
    </tbody>
</table>
<table id="table_id">
    <thead>
        <tr>
            <th>Id</th>
            <th>Name</th>
            <th>Genus</th>
        </tr>
    </thead>
    <tbody ng-repeat="plant in plants">
        <tr>
            <td>{{plant.Id}}</td>
            <td><a href="#/plants/{{plant.Id}}">{{plant.Name}}</a></td>
            <td>{{plant.Genus}}</td>
        </tr>
    </tbody>
</table>

This is my plants.html file and it uses the plants object which I have added to the scope in my controller.

See how I add the link (the # is important).

The next file is the detail view, plant.html.

HTML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<table id="table_id">
    <tr>
        <th>Id</th>
        <th>{{plant.Id}}</th>
    </tr>
    <tr>
        <th>Name</th>
        <th>{{plant.Name}}</th>
    </tr>
    <tr>
        <th>Genus</th>
        <th>{{plant.Genus}}</th>
    </tr>
</table>
<table id="table_id">
    <tr>
        <th>Id</th>
        <th>{{plant.Id}}</th>
    </tr>
    <tr>
        <th>Name</th>
        <th>{{plant.Name}}</th>
    </tr>
    <tr>
        <th>Genus</th>
        <th>{{plant.Genus}}</th>
    </tr>
</table>

Here I use plant because that is what I used to add the the scope in my controller.

And that is it.

Here are the screenshots. Look also at the url in the addressbarr.

The plants.

And here the detail view.

Conclusion

Yeah, uhm. Not sure. Not saying this is bad, but how will this scale ;-). One thing is for sure, the documentation was very good to get my started. Not that I read it before beginning but once I did, it helped.