Angular Walkthrough

Table of Contents [Hide/Show]


   Overview
   Walk-Through
      Initial Setup
      Wiring Up Angular
      Retrieving Data
      Updating Data


Overview

This article walks through the steps to create a simple Angular-based web app.

Walk-Through

Initial Setup

1. Within Visual Studio, create a new app, selecting Web > ASP.NET MVC 4 Web Application. Specify the "Empty" template and the Razor view engine.

2. Add Angular via NuGet: Project > References > Right-Click > Manage NuGet packages > Online > Search for "angular" > Install "Angular JS"

3. Under the website root folder, create a /Scripts/MyAngularApp folder.

4. Within the /Scripts/MyAngularApp folder, create app.js with the following code.

var myAngularApp = angular.module("myAngularApp", ["ngResource", "ngRoute"]).
    config(function ($routeProvider) {

        $routeProvider
            .when('/Team', { controller: 'TeamDashboardController', templateUrl: 'Views/Angular/TeamDashboard.html' })
            .otherwise({ redirectTo: '/Team' });

    });

4. Create the /Views/Shared/_Layout.cshtml file with the following code. The key items are the ng-app attribute on the body tag, and the script references to angular.min.js and app.js.

@{
    Layout = null;
}
<html>
    <head>
        <script src="~/Scripts/angular.min.js"></script>
        <script src="~/Scripts/angular-resource.min.js"></script>
        <script src="~/Scripts/angular-route.min.js"></script>
        <script src="/Scripts/MyAngularApp/app.js"></script>
        <script type="text/javascript" src="/Scripts/MyAngularApp/controllers/TeamDashboardController.js"></script>
        @RenderSection("head", required: false)
    </head>
    <body ng-app="myAngularApp">
        <h1>My Angular App</h1>
        @RenderBody()
    </body>
</html>

5. Create a Home controller with an Index method.

6. Create a view for the Home/Index method, specifying a layout file of ~/Views/Shared/_Layout.cshtml

7. Run your website and verify the /Home/Index page appears as expected. At this point, the site is rather trivial.

Wiring Up Angular

1. Change the code in /Views/Home/Index.cshtml to add the following line of code. The ng-view Angular directive is what triggers Angular to use the routes in app.js

<div ng-view></div>

2. Create the folder /Views/Angular and add the file TeamDashboard.html with the following content.

<h3>This is the Team Dashboard</h3>

{{ message }}

3. Create the folder /Scripts/MyAngularApp/controllers (this is only for organizational purposes), and a new JavaScript file in it called TeamDashboardController.js with the following content.

'use strict';

myAngularApp.controller('TeamDashboardController', function ($scope) {
    $scope.message = "Hello world!";
});

4. Add a new controller called AngularController and using the template of an Empty MVC Controller . Include the following code

Add Controller dialog

Add Controller dialog


public class AngularController : Controller
{
    public ActionResult Template(string templateName)
    {
        if (string.IsNullOrWhiteSpace(templateName))
        {
            return HttpNotFound();
        }

        return PartialView(templateName);
    }
}

5. In your /App_Start folder, edit the RouteConfig class by adding a new route to the RegisterRoutes method, as follows.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        /* Begin new route */
        routes.MapRoute(
                name: "TemplateRoute",
                url: "Templates/{templateName}.html",
                defaults: new { controller = "Angular", action = "Template"},
                constraints:new{templateName=@"[a-zA-Z0-9\-_]+"}
            );
        /* End new route */

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Run your website. At this point you should see two additional lines: "This is the Team Dashboard" and "Hello world!". The latter message is from the message code in TeamDashboard.html.

Retrieving Data

1. Create an Entity Data Model (EDMX) within your project, and point it at the AngularTraining database.

2. Create the folder /Controllers/api, then create a new API controller within it called PersonController with the following code.

public class PersonController : ApiController
{
    [HttpGet]
    public List<AngularTraining.Models.Person> Index()
    {
        using (var db = new AngularTraining.Models.AngularTrainingEntities1())
        {
            return db.People.ToList();
        }
    }

}

3. Within your WebApiConfig.cs file (found within the App_Start folder) change the code for the Register method to the following.

public static void Register(HttpConfiguration config)
{

    config.Routes.MapHttpRoute(
        name: "LookupRoute",
        routeTemplate: "api/{controller}/{action}",
        defaults: new { action = "Index" }
        );

}

4. Create a new folder called /Scripts/MyAngularApp/services and create the file "PersonService.js" within it with the following content.

'use strict';

myAngularApp.factory('PersonService', function ($http, $q) {
  
    return {

        getPeople: function () {

            var url = '/api/person',
                deferred = $q.defer();

            $http.get(url)
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, headers, config) {
                    deferred.reject();
                });

            return deferred.promise;

        }

    }
});

5. Within the _Layout.cshtml file add a script reference to PersonService.js

@{
    Layout = null;
}
<html>
    <head>
        <script src="~/Scripts/angular.min.js"></script>
        <script src="~/Scripts/angular-resource.min.js"></script>
        <script src="/Scripts/MyAngularApp/app.js"></script>

        <!-- Add the following line -->
        <script src="/Scripts/MyAngularApp/services/PersonService.js"></script>

        <script type="text/javascript" src="/Scripts/MyAngularApp/controllers/TeamDashboardController.js"></script>
        @RenderSection("head", required: false)
    </head>
    <body ng-app="myAngularApp">
        <h1>My Angular App</h1>
        @RenderBody()
    </body>
</html>

6. Within the TeamDashboardController.js file, change your code to call the PersonService

'use strict';

/* Note that [PersonService] was added as an argument after [$scope] */
myAngularApp.controller('TeamDashboardController', function ($scope, PersonService) {
    
    $scope.message = "Hello world!";

    /* Add this service call */
    PersonService.getPeople().then(function (data) {
        $scope.people = data;
    });
});

7. Add the following code to the bottom of your TeamDashboard.html file

<ul>
    <li ng-repeat="person in people">{{person.FirstName}} {{person.LastName}}</li>
</ul>

8. Run your website. You should see a bulleted list of all people in the database.

Updating Data

1. Within your PersonController.cs file, add the PostPerson method, as shown below.

[HttpPost]
public AngularTraining.Models.Person PostPerson(AngularTraining.Models.Person person)
{
    using (var db = new AngularTraining.Models.AngularTrainingEntities1())
    {
        var d = db.People.FirstOrDefault(o => o.PersonID == person.PersonID);

        if (d == null)
        {
            d = new AngularTraining.Models.Person();
            db.People.Add(d);
        }

        d.FirstName = person.FirstName;
        d.LastName = person.LastName;
        d.PhoneNum = person.PhoneNum;

        db.SaveChanges();

        return d;
    }
}

2. Within your PersonService.js file, add the postPerson function as shown below.

'use strict';

myAngularApp.factory('PersonService', function ($http, $q) {
  
    return {

        getPeople: function () {

            var url = '/api/person',
                deferred = $q.defer();

            $http.get(url)
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, headers, config) {
                    deferred.reject();
                });

            return deferred.promise;

        },

        /*--- Start New Code ---*/  
        postPerson: function (person) {

            var url = '/api/person/postPerson',
                deferred = $q.defer();

            $http.post(url,person)
                .success(function (data) {
                    deferred.resolve(data);
                })
                .error(function (data, status, headers, config) {
                    deferred.reject();
                });

            return deferred.promise;

        }
        /*--- End New Code ---*/

    }
});

3. Within your TeamDashboardController.js file, add the savePerson function, as shown below.

'use strict';

myAngularApp.controller('TeamDashboardController', function ($scope, PersonService) {
    
    $scope.message = "Hello world!";

    PersonService.getPeople().then(function (data) {
        $scope.people = data;
    });

    /*--- Start New Code ---*/
    $scope.savePerson = function (person) {
            
        PersonService.postPerson(person).then(function (data) { alert('Person saved'); });

    }
    /*--- End New Code ---*/

});

4. Within your TeamDashboard.html file, add code to display the names in textboxes with a Save button, as shown below.

<h3>This is the Team Dashboard</h3>

{{ message }}

<ul>
    <li ng-repeat="person in people">{{person.LastName}}, {{person.FirstName}} </li>
</ul>

<!-- Start New Code -->
<div ng-repeat="person in people" style="width:100%">
    <input type="text" ng-model="person.FirstName" /> 
    <input type="text" ng-model="person.LastName" /> 
    <button ng-click="savePerson(person)" >Save</button>
</div>
<!-- End New Code -->

5. Run your website. Notice when you change a name in a textbox, that the "static" text in the bulleted list updates dynamically as you type.

6. When you click a Save button