Creating a Site with AngularJS

The AngularJS client-side JavaScript framework is a powerful (and popular) library that allows you to more easily create SPAs that do not refresh for every user action. This provides a better user experience without the use of a browser plug-in.

AngularJS can be used with just an HTML page as your view. The JavaScript works to call the server Web API as needed to update the model and persist data. However, you can also combine Angular with ASP.NET MVC (and similar technologies). This section will walk you through the basics of AngularJS and a sample using it with an ASP.NET 5 MVC 6 project template.

Understanding AngularJS Basics

AngularJS leverages the MVC pattern on the client to keep your JavaScript code organized. It also provides a repeatable pattern for handling data and binding that data to views. This is similar to Knockout (shown in the prior section) but takes a different approach to organizing your code and binding your model and view.

The following outlines the basics of the MVC pattern in AngularJS. Each item is also shown with its AngularJS directive preceded with ng. (The ng is just a way to refer to the word “Angular.”) A directive in Angular is markup that instructs Angular as to what you are trying to accomplish. You will see that there are a lot of directives in Angular.

Image Model (ng-model)—The model is a JavaScript client representation of the data used by your view. You typically still maintain an API on the server for retrieving and persisting the data (also called a model). However, you work with that data on the client as a JavaScript model object. The model gets exposed by the controller (which is sometimes referred to as a view model).

You use the ng-model directive to indicate that a given section (like a <div> tag) works with a specific model from your Angular application.

Image View (ng-app)—The view represents your HTML markup for the page. You use Angular to bind items from your model to the view. This way, as the model updates, so does the view. Angular defines the view as a projection of your model using an HTML template.

You use the directive ng-app to wire a specific application to your view. You can do so inside the <html> tag for the page or inside a specific page section, such as a <div>.

Image Controller (ng-controller)—A JavaScript function that you write to create an instance of your model (typically defined as $scope). The controller works to bind properties of your model to the page and keep the page and model in sync. You can think of the controller like a view model. Angular does not use a strict version of MVC; rather, it is a variation designed for a specific purpose. The controller allows you to move your application logic out of the page and into code (where it belongs). This also makes your front end more testable.

You use the ng-controller directive to attach a controller to your page. You can do so inside the <body> tag or another tag such as <div>. You cannot use items of the controller outside the scope of where the controller is used in the markup. You can add multiple controllers to a page, each within its own page section. You can also work with multiple controllers in the same page section.

Let’s start by looking at a simple example. We will again leverage the “calculate pace” example from the prior sections to show comparison (between JavaScript, jQuery, Knockout, and now AngularJS). We will create the example inside an ASP.NET 5 site (see the next section for creating the site and adding AngularJS to your project), but we will use AngularJS to do most of the work.

The view page (called BasicSample.cshtml) uses AngularJS for binding to a model via a controller. The view page we are examining is an ASP.NET MVC view that uses a _Layout.cshtml page as its base (which includes a <script> tag pointing to the AngularJS library). This sample page is shown in Listing 18.8 (which includes line numbers for reference).

There are a number of AngularJS-specific directives to point out; the following walks you through each:

Image Line 07—Use the ng-app directive to indicate the module (or AngularJS application) that this page is using (<div ng-app="basic-sample">). It is possible to register multiple modules on a page, each specific to an app and a section of the page.

Image Line 08—The ng-controller directive indicates that the given <div> and (its contents) is to be used within the application’s controller, BasicSampleCtrl. The controller is part of the module (ng-app="basic-sample"). You can have multiple controllers in an application and use multiple controllers within the same page for different purposes. (This helps keep your code clean and maintainable.)

Image Line 09 and 11—This is a user form that uses <input> tags to be bound to the AngularJS model. There are a number of binding directives in AngularJS. The most used is one-way data binding. The syntax for this is as follows: <input type="text" value="{{ basicModel.distance }}" />.

However, in this case, we want two-way data binding that updates the model as a user enters data into a given field. Therefore, we use the ng-model directive. This represents two-way data binding in Angular (from the code to the UI and from the UI back to the code). Without two-way data binding, we would have to scrape the input from the form elements after a user executes an action such as changing focus (blur) and using jQuery (or, we could process the data on the server via a POST, but that is not responsive).

Image Line 17—This uses the ng-bind directive to bind a <span> to the results of the model’s method, pace(). This is also a two-way binding. The method calculates based on user input. It will update real time given our use of ng-model binding and ng-bind.

Image Line 24—This line simply includes the AngularJS script for the page. You will see that script in a moment. It includes definitions for the AngularJS module, controller, and a JavaScript model.

LISTING 18.8 A Simple Angular View That Uses Two-Way Data Binding


01  @{
02    ViewBag.Title = "Basic Angular Sample";
03  }
04
05  <h2>@ViewBag.Title</h2>
06
07  <div ng-app="basic-sample">
08    <div ng-controller="BasicSampleCtrl">
09      <p>Distance (miles): <input type="text" ng-model="basicModel.distance"
10                                  class="form-control" /></p>
11      <p>Time (minutes): <input type="text" ng-model="basicModel.time"
12                                class="form-control" /></p>
13      <hr />
14      <p>
15        <strong>
16          Calculated pace (mins/mile):
17            <span ng-bind="basicModel.pace()" ></span>
18        </strong>
19      </p>
20    </div>
21  </div>
22
23  @section Scripts {
24    <script src="~/app.js"></script>
25  }


The AngularJS code defines a module, a controller, and a model. This code is shown in Listing 18.9 (again, with line numbers for reference). The following highlights key areas within this code (by line number):

Image Line 05—This line uses the angular object to register an angular module called basic-sample. Think of an Angular module as an application. You typically create a new module for each main feature of your application. Modules contain Angular controllers. You can also mark a given module as dependent on one or more other modules using the parameter array in the second argument.

Image Line 06—This creates a controller called BasicSampleCtrl that is added to the module. You can also use the syntax moduleName.controller() to add a new module to a given controller.

Image Line 10—The $scope for a given controller is used to represent the model (or view model). You can define $scope inside the controller. Alternatively, you can keep your models separate (as in this example) and instantiate an instance and assign it to $scope. The content of $scope is what can be bound to your page by Angular.

Image Lines 14–21—This is the actual model. It is just the class we have used in previous examples.

LISTING 18.9 The AngularJS Code for the Page Inside a File Called app.js


01  (function () {
02    'use strict';
03
04    //The angular module definition
05    angular.module('basic-sample', [])
06      .controller(BasicSampleCtrl, BasicSampleCtrl);
07
08    //The controller defining the model as $scope
09    function BasicSampleCtrl($scope) {
10      $scope.basicModel = new BasicModel();
11    }
12  })();
13
14  //The model
15  function BasicModel() {
16    this.time = 100;
17    this.distance = 10;
18    this.pace = function () {
19      return (this.time / this.distance).toFixed(2);
20    };
21  };


When you run this application, you get the screen shown in Figure 18.29. Again, because we are using two-way binding, as a user types in the input fields, the pace is calculated and updated automatically by Angular binding. We will look at some of the concerns of building a larger Angular example with ASP.NET 5 next.

Image

FIGURE 18.29 The basic pace sample running as an AngularJS project.

Adding AngularJS to Your Project

There are file templates for AngularJS built into Visual Studio. There is also IntelliSense by default. However, Angular is not installed by default as a client framework in the ASP.NET template. This is where Bower support in ASP.NET can again help. The following walks you through adding AngularJS to an ASP.NET 5 MVC 6 template:

1. Start with a new or existing site built off the ASP.NET 5 Web Site template (which includes support for Bower).

2. Open bower.json from Solution Explorer. Inside the Dependencies section at the top of the file, add Angular as a dependency. You should get IntelliSense here and see the framework as well as version 1.4.1 (latest at the time of writing). Refer to Figure 18.23 as an example (for Knockout).

3. The next step is to add Angular to the copy task in gulpfile.js. Gulp will use the copy task to move the Angular.js file to the wwwroot/lib folder.

Open gulpfile.js and find the code for gulp.task("copy")...; add the following to the end of the list in this method call:

"angular": "angular/angular*.{js,map}"

This tells the Gulp task to copy the .js source files from the bower_components folder to the wwwroot/lib. This will include the debug version of Angular (angular.js) and the minified version (angular.min.js).

4. Open Task Runner Explorer and run the clean and copy tasks to move the Angular files into wwwroot/lib. After running the tasks, use Solution Explorer to navigate to wwwroot/lib/Angular to see the results.

5. You also need to add Angular to your page before you can use it. In ASP.NET MVC, this can be done site-wide inside the _Layout.cshtml page provided you intend to use the framework across your site. (Otherwise, you can add to specific pages where you intend to use it.).

Inside the _Layout.cshtml, scroll to near the bottom of the page. Find the <environment names="Development"> tag. Add the following <script> tag inside this tag to include a reference to the Knockout library.

<script src="~/lib/angular/angular.js"></script>

As an optional step, you can add the minified version to the <environment names="Staging,Production"> section. The following is the additional <script/> tag to add to this section. Note, you could also point to a content delivery network (CDN) instead of a local file.

<script src="~/lib/angular/angular.min.js"></script>

Creating an App with AngularJS

We will now look at building a larger application with AngularJS. We will stick with a similar application that we used in the Knockout sample to allow for comparison between the two frameworks. The application starts with an ASP.NET 5 starter web template. We assume that the project is set up to include the AngularJS library as shown in the prior section. We also assume you are using a Gulp task to output your script files to the wwwroot directory. (See the prior section, “Minify (or Copy) Your JavaScript with Gulp”). Once you’ve completed those tasks, it is time to get started.

Create the Model (on the Server)

The model for the server-side MVC code will be the same as the model created in the Knockout example (BikeLog). Refer to Listing 18.4 for an example.

Create the Controller (on the Server)

The ASP.NET MVC controller will be the same as the one used in the Knockout sample. Refer to Figure 18.25 for an example. You can get the details of this controller from the source code for the book.

Create the AngularJS Application, Controller, and Initial Service

We will write the server-side elements by first focusing on the initial Angular JavaScript to define the application. The following walks you through these steps:

1. This example will need to call the Web API RESTful services inside the controller. Like many things in Angular, there are a few ways to do so. You can use the $http method that exists inside of Angular and works similarly to jQuery. Alternatively, you can use the Angular $resource service, which can make your code somewhat easier to understand and maintain.

We will use this $resource approach to call our Web API services. This feature is part of a separate angular library called angular-resource. We need to include this library in our project.

Open Bower.json and add "angular-resource": "~1.4.1" to the dependencies list (under the Angular dependency). Save the file. You should see the package under Dependencies/Bower.

Open gulpfile.js and find the code for gulp.task("copy")...; add the following to the end of the list in this method call:

"angular-resource": "angular-resource/angular-resource*.{js,map}"

Finally, add this library to the markup inside the shared file _Layout.cshtml, <environment names="Development"> section as in the following.

<script src="~/lib/angular-resource/angular-resource.js"></script>

You may also add the minified version of this file to the <environment names="Staging,Production"> section as in the following.

<script src="~/lib/angular-resource/angular-resource.min.js"></script>

2. Create an Assets folder inside your project. Add a JavaScript file called app.js inside this folder.

3. Next, we will configure Gulp to copy the JavaScript files from the Assets folder to the wwwroot upon project build. In this case, we will not minify the files. Instead, we will just copy them as the gulp-uglify plugin in its current version does not always work well with Angular (without customizations).

Start by opening gulpfile.js. Add the highlighted lines below to the paths object. This will setup paths for the Assets folder and the wwwroot.

var paths = {
  bower: "./bower_components/",
  lib: "./" + project.webroot + "/lib/",
  root: "./" + project.webroot + "/",
  assets: "./assets/"
};

Next, create a Gulp task inside gulpfile.js to copy files from Assets to wwwroot. This task should look as follows:

gulp.task("copyAssets", function () {
  var assets = {
    "assets": "*.js"
  }
  for (var file in assets) {
    gulp.src(paths.assets + assets[file])
      .pipe(gulp.dest(paths.root + file));
  }
});

Finally, use Task Runner Explorer to bind the new copyAssets to the After Build action. This will ensure this file is output upon a new build.


Note

We put all the Angular code for the project in this example inside a single file, app.js. You could, however, create separate folders under Assets for Controllers, Services, and the like. You can then use Gulp to either output these files separately at build or “uglify” them together as a single file. Each development group has a specific way it likes to organize its code, including the many JavaScript files used by an AngularJS application.


4. Open app.js and define an AngularJS module (application) as an anonymous function nested inside another anonymous function. Call this module rideLog-app, as in the code that follows. Notice that the module definition includes the dependency ngResource. This indicates that the module is dependent on angular-resource (for creating services).

//The rideLog-sample module, controller, and services
(function () {
  'use strict';

  //The angular application definition
  var app = angular.module('rideLog-app', ['ngResource']);

})();

5. Define an Angular service for calling the Web API Get method to return a list of ride log entries (defined back in Figure 18.25). We add this code to the same app.js file.

The code uses the app reference created earlier when defining the module. It uses app.factory to add a service called LogSrv as a $resource. Notice that we pass the URL to $resource. We also define the service using the query argument. Here we state that the HTTP method is GET, there are no parameters, and we expect an array as a return value.

app.factory('LogSrv', ['$resource',
function ($resource) {
  return $resource('/api/bikelogsrv/', {}, {
    query: { method: 'GET', params: {}, isArray: true }
  });
}]);

6. We now need to define the controller for this page. We add the controller to the module again using the app reference. This controller will use $scope to set the model data (logEntries). It will also depend on the LogSrv created earlier to retrieve this data from the HTTP call (query). Angular automatically decodes JSON from the service into a JavaScript model (in this case, an array). The following shows an example of this code.

//The controller defining the model as $scope
app.controller('RideLogCtrl', ['$scope', 'LogSrv', function ($scope, LogSrv) {
  $scope.logEntries = LogSrv.query();
}]);

The next step is to bind this application to an HTML view.


Tip

Visual Studio ships with item templates for key AngularJS features. These templates create new .js files stubbed to work with AngularJS. Templates include controller, controller using $scope, directive, factory (for working with services), and module. This example uses a single file, app.js. These templates are useful if you write a lot of AngularJS and maintain separate files.


Bind the AngularJS Application to a Bike Log List View

Let’s now look at how you can bind the angular module, controller, and data to an HTML view. The following walks you through this task:

1. Inside Solution Explorer, navigate to the Views folder. Right-click this folder to add a new folder called BikeLog.

2. Right-click the BikeLog folder and choose Add, New Item. Select the template MVC View Page. Name this new page Index.cshtml and click the Add button.

3. Add a <script> tag pointing to the app.js file at the end of the page, inside a Scripts section. Recall that the file will be the one that Gulp outputs to wwwroot. The file will include the JavaScript created previously. This Script section should look like this:

@section Scripts {
  <script src="~/assets/app.js"></script>
}

4. Indicate that the page uses the Angular application rideLog-app by adding the following <div> tag (also marks the tag as a Bootstrap row).

<div class="row" ng-app="rideLog-app">

5. Add another <div> tag inside the previous one for defining the controller, as in the following (also marks the tag width using Bootstrap).

<div class="col-md-12" ng-controller="RideLogCtrl">

6. Create a <table> to hold each bike log entry as a row. We will use the Angular directive ng-repeat to indicate a template for the table body. This directive will then repeat for each item (entry) in the array defined in our scope (logEntries).

We will then use one-way binding to bind items (as entry) from the logEntries array. Angular creates and maps these objects to the array automatically when we call the service.

Listing 18.10 shows the completed view page bound to view app, controller, and model (controller data).

LISTING 18.10 The Markup for the Bike Log Index.cshtml page Bound Using AngularJS


@{
  ViewBag.Title = "Bike Log Sample - Angular";
}

<h2>@ViewBag.Title</h2>
<p>See the bike log data for recent rides and track new ones.</p>

<div class="row" ng-app="rideLog-app">
  <div class="col-md-12" ng-controller="RideLogCtrl">
    <hr />
    <table>
      <thead>
        <tr>
          <td>Id</td>
          <td>Description</td>
          <td>Time (minutes)</td>
          <td>Distance (miles)</td>
          <td align="center">Pace (min/mile)</td>
          <td></td>
        </tr>
      </thead>
      <tbody ng-repeat="entry in logEntries">
        <tr>
          <td>{{entry.Id}}</td>
          <td>{{entry.Description}}</td>
          <td>{{entry.TimeMinutes}}</td>
          <td>{{entry.DistanceMiles}}</td>
        </tr>
      </tbody>
    </table>
    <hr />
  </div>
</div>
@section Scripts {
  <script src="~/app.js"></script>
}


You can now run the application and view the results. Figure 18.30 shows the page and its table bound to the Web API data by Angular.

Image

FIGURE 18.30 The Web API data bound to the page using Angular.

Turn the Page into a Form

Let’s now turn the view into a form using two-way data binding. We will also add the calculation for pace. The following walks you through this process:

1. Open app.js. Inside the app.controller definition, add the method setPace to the $scope. This method should take time and distance as parameters. The following shows an example.

$scope.setPace = function (t, d) {
  return (t / d).toFixed(2);
};

2. Next, open Index.cshtml. Change the data inside the <tr> template to use <input> tags and two-way binding using the directives ng-bind and ng-model. Add a new column that calls the setPace method for each entry in logEntries passing in both time and distance. This binding will allow the page to automatically update as a user changes a value. The following shows an example.

<tbody ng-repeat="entry in logEntries">
  <tr>
    <td><span ng-bind="entry.Id"></span></td>
    <td>
      <input type="text" ng-model="entry.Description" />
    </td>
    <td>
      <input type="text" ng-model="entry.TimeMinutes" />
    </td>
    <td>
      <input type="text" ng-model="entry.DistanceMiles" />
    </td>
    <td align="center">
      <span ng-bind="setPace(entry.TimeMinutes, entry.DistanceMiles)"></span>
    </td>
    @*<td><a href="#">delete</a></td>*@
  </tr>
</tbody>

You can again run the page. Figure 18.31 shows an example. Notice that as you type in the <input> fields, the Pace value is automatically updated thanks to two-way data binding in AngularJS.

Image

FIGURE 18.31 The Angular page turned into a form using two-way data binding.

Add a New Log Entry

Next, we will create a button to allow a user to add a new ride entry to the form. To do so, we will use the ng-click Angular directive to define what happens when a user presses a button. Let’s get started.

1. Inside app.js, add the method called addEntry() to the $scope inside the controller definition. This method should just push a new item on to the logEntries array (already bound to our form). The following shows an example.

$scope.addEntry = function () {
  this.logEntries.push(
    { Id: 0, Description: '', TimeMinutes: 0, DistanceMiles: 0 });
};

2. Add a button to the Index.cshtml page near the top (before <table>). Use the ng-click directive to set the click event of the button to the addEntry method of the $scope, as in the following.

<button type="button" class="btn"
        ng-click="addEntry()">Add New Entry</button>

Run the page and view the results. Figure 18.32 shows an example. Notice that you can add new items every time you click the Add New Entry button. These items are automatically bound to the form using the same template as the other items in the array.

Image

FIGURE 18.32 Adding new rows to the page using the ng-click directive to bind to a method defined in the model.

Delete an Entry

Let’s now take a look at deleting an entry from the list of bike log items. Recall that Knockout used a special array to mark an item as _destroy. This allowed us to not show the item in the UI and have this information available to us when the data was posted to the server. Unfortunately, Angular does not have anything built in along those lines. However, we can create a similar feature to track an item as being deleted and filter the view accordingly. The following steps you through this process:

1. The model on the server already contains a property called _destroy. Therefore, the object sent to Angular by the service also includes this property. We will use it here.

2. Open app.js and add a function called deleteEntry to the $scope inside the controller. This function should take an entry item as a parameter. It then simply sets the _destroy property to true, as in the following.

$scope.deleteEntry = function (entry) {
  entry._destroy = true;
};

3. Inside the page markup of Index.cshtml, add a column with an <a> tag for deleting a row. This tag should use the ng-click directive to bind to the deleteEntry method, as in the following:

<td><a href="#" ng-click="deleteEntry(entry)">delete</a></td>

4. Next, use the ng-hide directive to show the row based on the value of _destroy. The following shows an example.

<tr ng-hide="entry._destroy">

You can run the application and view the results, as shown in Figure 18.33. Notice that as you click Delete, the view is filtered to no longer show the deleted item. However, the item is still in the array so that the delete can be processed back on the server.

Image

FIGURE 18.33 Use ng-hide to indicate that an item should be hidden based on a Boolean value in your model.


Note

Another option is to remove the item directly from the server using another service and calling it with HTTP DELETE. In that case, we would create an Angular service that knew how to pass an id parameter and call HTTP DELETE. The source code for this book includes this example as well; it is commented in the app.js file under the deleteEntry method.


Save Changes

Let’s take a look at saving the form changes back to the database using the Web API. This is the same web service call we used in the Knockout sample. The following walks you through setting this up with Angular:

1. Start by adding a new button to the Index.cshtml form to allow a user to save changes. This button should use the directive ng-click to bind to a saveChanges method you will create in a moment. We will also include a <span> tag for displaying the results of the save action to the user.

<button type="button" class="btn"
        ng-click="saveChanges()">Save Changes</button>
<span class="text-success" id="success">{{ saveResult }}</span>

2. Inside app.js, extend the app.factory to include the additional service call to send a POST request to the Web API. This following shows this addition (along with an optional remove addition from the prior example).

app.factory('LogSrv', ['$resource',
function ($resource) {
  return $resource('/api/bikelogsrv/:id', {}, {
    query: { method: 'GET', params: {}, isArray: true },
    remove: { method: 'DELETE', params: { id: '@id' } },
    post: { method: 'POST',
            params: { logEntriesJson: '@logEntriesJson' } }
});
}]);

3. Add the saveChanges method to the model (using $scope). This method should call the post service and pass the logEntries data as a JSON string. Recall that the Web API method will use Newtonsoft.Json to deserialize the string into strong types on the server.

After making the call to post, we call the LogSrv.query() again to reset the list view. We then set the saveResult message and show it to the user using jQuery.

The following shows an example of saveChanges.

$scope.saveChanges = function () {
  //Post the save data.
  LogSrv.post({ logEntriesJson: JSON.stringify($scope.logEntries) });

  //Update the log entries array.
  $scope.logEntries = LogSrv.query();

  //Update the UI to show value saved.
  $scope.saveResult = 'Saved';
  $('#success').show();
  $('#success').fadeOut(2000);
};


Note

Internet Explorer (IE) will cache the query call from Angular. (Chrome will not.) You can fix this by setting the ResponseCache attribute on the Web API service to not allow caching. We have done so here in the sample code for the book.


You can again run the application and view the results. You can now edit, delete, and add new items and then save the changes to the server.


Tip

Remember that when using Gulp to output your code to wwwroot, the code running in the client is the code pushed to wwwroot (not the code inside your Scripts folder). If you need to debug your JavaScript, you set a breakpoint in the code file in wwwroot (and not the one in Scripts).


Doing More with AngularJS

This section should give you a good grasp of using the power of the Angular client framework. However, there is a lot more to Angular than we are able to show here. This includes many additional directives and filters that make writing responsive user interfaces easier. The following provides a few additional areas for further exploration.

Form Validation

Angular has built-in support for validating form field items. You can use Angular to set specific rules on <input> elements such as email, date, number, required, URL, and more. Angular will then validate these items on your behalf.

You can also tell Angular not to submit the form if it is not valid using the directive ng-submit on a <form> tag as in the following (where submitMethod is a method on your model that is called when the form is submitted).

<form name="myForm" ng-submit="myForm.$valid && submitMethod">

Angular also keeps track of each field using CSS classes that tell you if a value has not been changed (ng-pristine), has been changed and is not valid (ng-dirty.ng-invalid), or has been changed and is valid (ng-dirty.ng-valid). You can use these classes inside your site.css to create styles that highlight your form elements based on these validation conditions.

Angular Directives

The examples thus far have presented many of the AngularJS directives such as ng-app, ng-model, ng-controller, ng-bind, ng-repeat, ng-click, and more. However, there are many more. In addition, Angular supports creating your own custom directives that allow you to write more expressive, easy-to-read HTML that shows behavior and intent.

The following lists additional Angular directives. (It is not a complete reference.)

Image ng-model—Bind to form elements such as text box, check box, text area, and radio buttons.

Image ng-submit—Allows you to bind an angular expression to an onsubmit event for a <form>.

Image ng-show, ng-hide—Used to show and hide elements within your form based on a Boolean value from your model.

Image ng-src—Used to map data in your model to the src attribute of an <img> tag.

Image ng-click, ngChange, ngBlur, ngFocus (and more)—Used to bind user events to methods in your model.

Image ng-class—Used to set the CSS class based on a value from your model or an expression.

Filters

Angular includes a set of built-in filters that make displaying data in the UI much easier. These filters are used in your markup using the “pipe” style, as in {{ data | filter:options }}. There are filters for currency, date, number, orderby, uppercase, and more. The following shows a model binding that uses a filter to ensure the value is shown as currency format.

<span>{{price | currency}}</span>


Note

Microsoft and Google announced that they are going to leverage TypeScript as the new language for Angular development. Expect to see the next version of Angular made even easier to use with TypeScript.


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset