Você está na página 1de 182

AngularJS Introduction

Previous
Next Chapter
AngularJS is a JavaScript framework. It can be added to an HTML page with a
<script> tag.
AngularJS extends HTML attributes with Directives, and binds data to HTML with
Expressions.

AngularJS is a JavaScript Framework


AngularJS is a JavaScript framework. It is a library written in JavaScript.
AngularJS is distributed as a JavaScript file, and can be added to a web page with a
script tag:
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></scri
pt>

AngularJS Extends HTML


AngularJS extends HTML with ng-directives.
The ng-app directive defines an AngularJS application.
The ng-model directive binds the value of HTML controls (input, select, textarea) to
application data.
The ng-bind directive binds application data to the HTML view.

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></scri
pt>
</head>
<body>

<div ng-app="">
<p>Name: <input type="text" ng-model="name"></p>
<p ng-bind="name"></p>
</div>
</body>
</html>
Try it Yourself

Example explained:
AngularJS starts automatically when the web page has loaded.
The ng-app directive tells AngularJS that the <div> element is the "owner" of an
AngularJS application.
The ng-model directive binds the value of the input field to the application variable
name.
The ng-bind directive binds the innerHTML of the <p> element to the application
variable name.

AngularJS Directives
As you have already seen, AngularJS directives are HTML attributes with an ng prefix.
The ng-init directive initialize AngularJS application variables.

AngularJS Example
<div ng-app="" ng-init="firstName='John'">
<p>The name is <span ng-bind="firstName"></span></p>
</div>
Try it Yourself

You can use data-ng-, instead of ng-, if you want to make your page HTML5 valid.

Alternatively with valid HTML5:

AngularJS Example
<div data-ng-app="" data-ng-init="firstName='John'">

<p>The name is <span data-ng-bind="firstName"></span></p>


</div>
Try it Yourself

You will learn a lot more about directives later in this tutorial.

AngularJS Expressions
AngularJS expressions are written inside double braces: {{ expression }}.
AngularJS expressions bind data to HTML the same way as the ng-bind directive.
AngularJS will "output" data exactly where the expression is written.

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<scriptsrc="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></scri
pt>
</head>
<body>
<div ng-app="">
<p>My first expression: {{ 5 + 5 }}</p>
</div>
</body>
</html>
Try it Yourself

You will learn more about expressions later in this tutorial.

AngularJS Controllers
AngularJS applications are controlled by controllers.
The ng-controller directive defines the controller.
The controller code will execute when the page loads.

AngularJS Example
<div ng-app="" ng-controller="personController">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<script>
function personController($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
}
</script>
Try it Yourself

You will learn a lot more about controllers later in this tutorial.

AngularJS Expressions
Previous
Next Chapter
AngularJS binds data to HTML using Expressions.

AngularJS Expressions
AngularJS expressions are written inside double braces: {{ expression }}.
AngularJS expressions binds data to HTML the same way as the ng-bind directive.
AngularJS will "output" data exactly where the expression is written.
AngularJS expressions are much like JavaScript expressions: They can contain
literals, operators, and variables.
Example {{ 5 + 5 }} or {{ firstName + " " + lastName }}

AngularJS Example
<!DOCTYPE html>
<html>

<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-app="">
<p>My first expression: {{ 5 + 5 }}</p>
</div>
</body>
</html>
Try it Yourself

If you remove the ng-app directive, HTML will display the expression as it is, without
solving it:

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div>
<p>My first expression: {{ 5 + 5 }}</p>
</div>
</body>
</html>
Try it Yourself

AngularJS Numbers
AngularJS numbers are like JavaScript numbers:

AngularJS Example
<div ng-app="" ng-init="quantity=1;cost=5">
<p>Total in dollar: {{ quantity * cost }}</p>

</div>
Try it Yourself

Same example using ng-bind:

AngularJS Example
<div ng-app="" ng-init="quantity=1;cost=5">
<p>Total in dollar: <span ng-bind="quantity * cost"></span></p>
</div>
Try it Yourself

Using ng-init is not very common. You will learn a better way to initialize data in
the chapter about controllers.

AngularJS Strings
AngularJS strings are like JavaScript strings:

AngularJS Example
<div ng-app="" ng-init="firstName='John';lastName='Doe'">
<p>The name is {{ firstName + " " + lastName }}</p>
</div>
Try it Yourself

Same example using ng-bind:

AngularJS Example
<div ng-app="" ng-init="firstName='John';lastName='Doe'">
<p>The name is <span ng-bind="firstName + ' ' + lastName"></span></p>
</div>
Try it Yourself

AngularJS Objects
6

AngularJS objects are like JavaScript objects:

AngularJS Example
<div ng-app="" ng-init="person={firstName:'John',lastName:'Doe'}">
<p>The name is {{ person.lastName }}</p>
</div>
Try it Yourself

Same example using ng-bind:

AngularJS Example
<div ng-app="" ng-init="person={firstName:'John',lastName:'Doe'}">
<p>The name is <span ng-bind="person.lastName"></span></p>
</div>
Try it Yourself

AngularJS Arrays
AngularJS arrays are like JavaScript arrays:

AngularJS Example
<div ng-app="" ng-init="points=[1,15,19,2,40]">
<p>The points are {{ points[2] }}</p>
</div>
Try it Yourself

Same example using ng-bind:

AngularJS Example
<div ng-app="" ng-init="points=[1,15,19,2,40]">
<p>The points are <span ng-bind="points[2]"></span></p>
</div>
Try it Yourself

AngularJS Directives
Previous
Next Chapter

AngularJS lets you extend HTML with new attributes called Directives.

AngularJS Directives
AngularJS directives are extended HTML attributes with the prefix ng-.
The ng-app directive initializes an AngularJS application.
The ng-init directive initialize application data.
The ng-model directive binds the value of HTML controls (input, select, textarea) to
application data.

AngularJS Example
<div ng-app="" ng-init="firstName='John'">
<p>Name: <input type="text" ng-model="firstName"></p>
<p>You wrote: {{ firstName }}</p>
</div>
Try it Yourself

The ng-app directive also tells AngularJS that the <div> element is the "owner" of the
AngularJS application.

Data Binding
The {{ firstName }} expression, in the example above, is an AngularJS data binding
expression.
Data binding in AngularJS, synchronizes AngularJS expressions with AngularJS data.
8

{{ firstName }} is synchronized with ng-model="firstName".


In the next example two text fields are synchronized with two ng-model directives:

AngularJS Example
<div ng-app="" ng-init="quantity=1;price=5">
Quantity: <input type="number" ng-model="quantity">
Costs: <input type="number" ng-model="price">
Total in dollar: {{ quantity * price }}
</div>
Try it Yourself

Using ng-init is not very common. You will learn how to initialize data in the
chapter about controllers.

Repeating HTML Elements


The ng-repeat directive repeats an HTML element:

AngularJS Example
<div ng-app="" ng-init="names=['Jani','Hege','Kai']">
<ul>
<li ng-repeat="x in names">
{{ x }}
</li>
</ul>
</div>
Try it Yourself

The ng-repeat directive used on an array of objects:

AngularJS Example
<div ng-app="" ng-init="names=[
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},

{name:'Kai',country:'Denmark'}]">
<ul>
<li ng-repeat="x in names">
{{ x.name + ', ' + x.country }}
</li>
</ul>
</div>
Try it Yourself

AngularJS is perfect for database CRUD (Create Read Update Delete) applications.
Just imagine if these objects were records from a database.

The ng-app Directive


The ng-app directive defines the root element of an AngularJS application.
The ng-app directive will auto-bootstrap (automatically initialize) the application
when a web page is loaded.
Later you will learn how ng-app can have a value (like ng-app="myModule"), to
connect code modules.

The ng-init Directive


The ng-init directive defines initial values for an AngularJS application.
Normally, you will not use ng-init. You will use a controller or module instead.
You will learn more about controllers and modules later.

The ng-model Directive


The ng-model directive binds the value of HTML controls (input, select, textarea) to
application data.
The ng-model directive can also:

10

Provide type validation for application data (number, email, required).


Provide status for application data (invalid, dirty, touched, error).

Provide CSS classes for HTML elements.

Bind HTML elements to HTML forms.

The ng-repeat Directive


The ng-repeat directive clones HTML elements once for each item in a collection (in
an array).

AngularJS Controllers
Previous
Next Chapter
AngularJS controllers control the data of AngularJS applications.
AngularJS controllers are regular JavaScript Objects.

AngularJS Controllers
AngularJS applications are controlled by controllers.
The ng-controller directive defines the application controller.
A controller is a JavaScript Object, created by a standard JavaScript object
constructor.

AngularJS Example
<div ng-app="" ng-controller="personController">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<script>
function personController($scope) {
$scope.firstName="John",

11

$scope.lastName="Doe"
}
</script>
Try it Yourself

Application explained:
The AngularJS application is defined by ng-app. The application runs inside a <div>.
The ng-controller directive names the controller object.
The personController function is a standard JavaScript object constructor.
AngularJS will invoke personController with a $scope object.
In AngularJS, $scope is the application object (the owner of application variables and
functions).
The personController creates two properties (variables) in the scope (firstName
andlastName).
The ng-model directives bind the input fields to the controller properties (firstName
and lastName).

Controller Methods
The example above demonstrated a controller object with two properties: lastName and
firstName.
A controller can also have methods (functions as object properties):

AngularJS Example
<div ng-app="" ng-controller="personController">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{fullName()}}
</div>
<script>
function personController($scope) {
$scope.firstName = "John",
$scope.lastName = "Doe",
$scope.fullName = function() {

12

return $scope.firstName + " " + $scope.lastName;


}
}
</script>
Try it Yourself

Controllers In External Files


In larger applications, it is common to store controllers in external files.
Just copy the code between the <script> tags into an external file named
personController.js:

AngularJS Example
<div ng-app="" ng-controller="personController">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</div>
<script src="personController.js"></script>
Try it Yourself

Another Example
For the next example we will create a new controller file:
function namesController($scope) {
$scope.names = [
{name:'Jani',country:'Norway'},
{name:'Hege',country:'Sweden'},
{name:'Kai',country:'Denmark'}
];
}
And then use the controller file in an application:

AngularJS Example
<div ng-app="" ng-controller="namesController">

13

<ul>
<li ng-repeat="x in names">
{{ x.name + ', ' + x.country }}
</li>
</ul>
</div>
<script src="namesController.js"></script>
Try it Yourself

AngularJS Filters
Previous
Next Chapter
Filters can be added to expressions and directives using a pipe character.

AngularJS Filters
AngularJS filters can be used to transform data:
Filter

Description

currency

Format a number to a currency format.

filter

Select a subset of items from an array.

lowercase

Format a string to lower case.

orderBy

Orders an array by an expression.

uppercase

Format a string to upper case.

Adding Filters to Expressions


A filter can be added to an expression with a pipe character (|) and a filter.
(For the next two examples we will use the person controller from the previous chapter)
The uppercase filter format strings to upper case:

AngularJS Example
14

<div ng-app="" ng-controller="personController">


<p>The name is {{ lastName | uppercase }}</p>
</div>
Try it Yourself

The lowercase filter format strings to lower case:

AngularJS Example
<div ng-app="" ng-controller="personController">
<p>The name is {{ lastName | lowercase }}</p>
</div>
Try it Yourself

The currency Filter


The currency filter formats a number as currency:

AngularJS Example
<div ng-app="" ng-controller="costController">
<input type="number" ng-model="quantity">
<input type="number" ng-model="price">
<p>Total = {{ (quantity * price) | currency }}</p>
</div>
Try it Yourself

Adding Filters to Directives


A filter can be added to a directive with a pipe character (|) and a filter.
The orderBy filter orders an array by an expression:

AngularJS Example
<div ng-app="" ng-controller="namesController">

15

<ul>
<li ng-repeat="x in names | orderBy:'country'">
{{ x.name + ', ' + x.country }}
</li>
</ul>
<div>
Try it Yourself

Filtering Input
An input filter can be added to a directive with a pipe character (|) and filter followed by
a colon and a model name.
The filter filter selects a subset of an array:

AngularJS Example
<div ng-app="" ng-controller="namesController">
<p><input type="text" ng-model="test"></p>
<ul>
<li ng-repeat="x in names | filter:test | orderBy:'country'">
{{ (x.name | uppercase) + ', ' + x.country }}
</li>
</ul>
</div>
Try it Yourself

AngularJS XMLHttpRequest
Previous
Next Chapter
$http is an AngularJS service for reading data from remote servers.

Reading a JSON File


The following static JSON file is stored on a web server:

http://www.w3schools.com/website/Customers_JSON.php
16

[
{
"Name" : "Alfreds Futterkiste",
"City" : "Berlin",
"Country" : "Germany"
},
{
"Name" : "Berglunds snabbkp",
"City" : "Lule",
"Country" : "Sweden"
},
{
"Name" : "Centro comercial Moctezuma",
"City" : "Mxico D.F.",
"Country" : "Mexico"
},
{
"Name" : "Ernst Handel",
"City" : "Graz",
"Country" : "Austria"
},
{
"Name" : "FISSA Fabrica Inter. Salchichas S.A.",
"City" : "Madrid",
"Country" : "Spain"
},
{
"Name" : "Galera del gastrnomo",
"City" : "Barcelona",
"Country" : "Spain"
},
{
"Name" : "Island Trading",
"City" : "Cowes",
"Country" : "UK"
},
{
"Name" : "Kniglich Essen",
"City" : "Brandenburg",
"Country" : "Germany"
},
{
"Name" : "Laughing Bacchus Wine Cellars",
"City" : "Vancouver",
"Country" : "Canada"
},
{
"Name" : "Magazzini Alimentari Riuniti",
"City" : "Bergamo",
"Country" : "Italy"
},
{

17

"Name" : "North/South",
"City" : "London",
"Country" : "UK"
},
{
"Name" : "Paris spcialits",
"City" : "Paris",
"Country" : "France"
},
{
"Name" : "Rattlesnake Canyon Grocery",
"City" : "Albuquerque",
"Country" : "USA"
},
{
"Name" : "Simons bistro",
"City" : "Kbenhavn",
"Country" : "Denmark"
},
{
"Name" : "The Big Cheese",
"City" : "Portland",
"Country" : "USA"
},
{
"Name" : "Vaffeljernet",
"City" : "rhus",
"Country" : "Denmark"
},
{
"Name" : "Wolski Zajazd",
"City" : "Warszawa",
"Country" : "Poland"
}
]

AngularJS $http
AngularJS $http is a core service for reading data from web servers.
$http.get(url) is the function to use for reading server data.

AngularJS Example
<div ng-app="" ng-controller="customersController">
<ul>
<ling-repeat="x in names">
{{ x.Name + ', ' + x.Country }}
</li>

18

</ul>
</div>
<script>
function customersController($scope,$http) {
$http.get("http://www.w3schools.com/website/Customers_JSON.php")
.success(function(response) {$scope.names = response;});
}
</script>
Try it Yourself

Application explained:
The AngularJS application is defined by ng-app. The application runs inside a <div>.
The ng-controller directive names the controller object.
The customersController function is a standard JavaScript object constructor.
AngularJS will invoke customersController with a $scope and$http object.
$scope is the application object (the owner of application variables and functions).
$http is an XMLHttpRequest object for requesting external data.
$http.get() reads static JSON data from
http://www.w3schools.com/website/Customers_JSON.php.
If success, the controller creates a property (names) in the scope, with JSON data
from the server.

The code above can also be used to fetch data from a database.

AngularJS Tables
Previous
Next Chapter
The ng-repeat directive is perfect for displaying tables.

Displaying Data in a Table


19

Displaying tables with angular is very simple:

AngularJS Example
<div ng-app="" ng-controller="customersController">
<table>
<tr ng-repeat="x in names">
<td>{{ x.Name }}</td>
<td>{{ x.Country }}</td>
</tr>
</table>
</div>
<script>
function customersController($scope,$http) {
$http.get("http://www.w3schools.com/website/Customers_JSON.php")
.success(function(response) {$scope.names = response;});
}
</script>
Try it Yourself

Displaying with CSS Style


To make it nice, add some CSS to the page:

CSS Style
<style>
table, th , td {
border: 1px solid grey;
border-collapse: collapse;
padding: 5px;
}
table tr:nth-child(odd) {
background-color: #f1f1f1;
}
table tr:nth-child(even) {
background-color: #ffffff;
}
</style>
Try it Yourself

Display with orderBy Filter


20

To sort the table, add an orderBy filter:

AngularJS Example
<table>
<tr ng-repeat="x in names | orderBy : 'Country'">
<td>{{ x.Name }}</td>
<td>{{ x.Country }}</td>
</tr>
</table>
Try it Yourself

Display with uppercase Filter


To display uppercase, add an uppercase filter:

AngularJS Example
<table>
<tr ng-repeat="x in names">
<td>{{ x.Name }}</td>
<td>{{ x.Country | uppercase}}</td>
</tr>
</table>
Try it Yourself

AngularJS SQL
Previous
Next Chapter

The code from the previous chapter can also be used to read from databases

Fetching Data From a PHP Server Running MySQL


AngularJS Example
<div ng-app="" ng-controller="customersController">
<table>
<trng-repeat="x in names">

21

<td>{{ x.Name }}</td>


<td>{{ x.Country }}</td>
</tr>
</table>
</div>
<script>
function customersController($scope,$http) {
var site = "http://www.w3schools.com";
var page = "/website/Customers_MySQL.php";
$http.get(site + page)
.success(function(response) {$scope.names = response;});
}
</script>
Try it Yourself

Fetching Data From an ASP.NET Server Running SQL


AngularJS Example
<div ng-app="" ng-controller="customersController">
<table>
<trng-repeat="x in names">
<td>{{ x.Name }}</td>
<td>{{ x.Country }}</td>
</tr>
</table>
</div>
<script>
function customersController($scope,$http) {
var site = "http://www.w3schools.com";
var page = "/website/Customers_SQL.aspx";
$http.get(site + page)
.success(function(response) {$scope.names = response;});
}
</script>

22

Try it Yourself

Server Code Examples


The following section is a listing of the server code used to fetch SQL data.
1. Using PHP and MySQL. Returning JSON.
2. Using PHP and MS Access. Returning JSON.
3. Using ASP.NET, VB, and MS Access. Returning JSON.
4. Using ASP.NET, Razor, and SQL Lite. Returning JSON.

Cross-Site HTTP Requests


Requests for data from a different server (than the requesting page), are called crosssite HTTP requests.
Cross-site requests are common on the web. Many pages load CSS, images, and scripts
from different servers.
In modern browsers, cross-site HTTP requests from scripts are restricted to same
site for security reasons.
The following line, in our PHP examples, has been added to allow cross-site access.
header("Access-Control-Allow-Origin: *");

1. Server Code PHP and MySQL


< ?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=UTF-8");
$conn = new mysqli("myServer", "myUser", "myPassword", "Northwind");
$result = $conn->query("SELECT CompanyName, City, Country FROM Customers");

23

$outp = "[";
while($rs = $result->fetch_array(MYSQLI_ASSOC)) {
if ($outp != "[") {$outp .= ",";}
$outp .= '{"Name":"' . $rs["CompanyName"] . '",';
$outp .= '"City":"' . $rs["City"] . '",';
$outp .= '"Country":"'. $rs["Country"] . '"}';
}
$outp .="]";
$conn->close();
echo($outp);
?>

2. Server Code PHP and MS Access


< ?php
header("Access-Control-Allow-Origin: *");
header("Content-Type: application/json; charset=ISO-8859-1");
$conn = new COM("ADODB.Connection");
$conn->open("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source=Northwind.mdb");
$rs = $conn->execute("SELECT CompanyName, City, Country FROM Customers");
$outp = "[";
while (!$rs->EOF) {
if ($outp != "[") {$outp .= ",";}
$outp .= '{"Name":"' . $rs["CompanyName"] . '",';
$outp .= '"City":"' . $rs["City"] . '",';
$outp .= '"Country":"'. $rs["Country"] . '"}';
$rs->MoveNext();
}
$outp .= "]";
$conn->close();
echo ($outp);
?>

24

3. Server Code ASP.NET, VB and MS Access


< %@ Import Namespace="System.IO"%>
<%@ Import Namespace="System.Data"%>
< %@ Import Namespace="System.Data.OleDb"%>
<%
Response.AppendHeader("Access-Control-Allow-Origin", "*")
Response.AppendHeader("Content-type", "application/json")
Dim conn As OleDbConnection
Dim objAdapter As OleDbDataAdapter
Dim objTable As DataTable
Dim objRow As DataRow
Dim objDataSet As New DataSet()
Dim outp
Dim c
conn = New OledbConnection("Provider=Microsoft.Jet.OLEDB.4.0;data
source=Northwind.mdb")
objAdapter = New OledbDataAdapter("SELECT CompanyName, City, Country FROM
Customers", conn)
objAdapter.Fill(objDataSet, "myTable")
objTable=objDataSet.Tables("myTable")
outp = "["
c = chr(34)
for each x in objTable.Rows
if outp <> "[" then outp = outp & ","
outp = outp & "{" & c & "Name" & c & ":" & c & x("CompanyName") & c & ","
outp = outp & c & "City" & c & ":" & c & x("City") & c & ","
outp = outp & c & "Country" & c & ":" & c & x("Country") & c & "}"
next
outp = outp & "]"
response.write(outp)
conn.close
%>

4. Server Code ASP.NET, VB Razor and SQL Lite


@{
Response.AppendHeader("Access-Control-Allow-Origin", "*")
Response.AppendHeader("Content-type", "application/json")
var db = Database.Open("Northwind");
var query = db.Query("SELECT CompanyName, City, Country FROM Customers");
25

var outp ="["


}
@foreach(var row in query)
{
if outp <> "[" then outp = outp + ","
outp = outp + "{" + c + "Name" + c + ":" + c + @row.CompanyName + c + ","
outp = outp + c + "City" + c + ":" + c + @row.City + c + ","
outp = outp + c + "Country" + c + ":" + c + @row.Country + c + "}"
}
outp = outp + "]"
@outp

AngularJS HTML DOM


Previous
Next Chapter
AngularJS has directives for binding application data to the attributes of HTML DOM
elements.

The ng-disabled Directive


The ng-disabled directive binds AngularJS application data to the disabled attribute of
HTML elements.

AngularJS Example
<div ng-app="">
<p>
<button ng-disabled="mySwitch">Click Me!</button>
</p>
<p>
<input type="checkbox" ng-model="mySwitch">Button
</p>
</div>
Try it Yourself

Application explained:
The ng-disabled directive binds the application data mySwitch to the HTML button's
disabled attribute.

26

The ng-model directive binds the value of the HTML checkbox element to the value of
mySwitch.
If the value of mySwitch evaluates to true, the button will be disabled:
<p>
<button disabled>Click Me!</button>
</p>
If the value of mySwitch evaluates to false, the button will not be disabled:
<p>
<button>Click Me!</button>
</p>

The ng-show Directive


The ng-show directive shows or hides an HTML element.

AngularJS Example
<div ng-app="">
<p ng-show="true">I am visible.</p>
<p ng-show="false">I am not visible.</p>
</div>
Try it Yourself

The ng-show directive shows (or hides) an HTML element based on the value of ngshow.
You can use any expression that evaluates to true or false:

AngularJS Example
<div ng-app="">
<p ng-show="hour > 12">I am visible.</p>
</div>
Try it Yourself

In the next chapter, there are more examples, using the click of a button to hide
HTML elements.

27

The ng-hide Directive


The ng-hide directive hides or shows an HTML element.

AngularJS Example
<div ng-app="">
<p ng-hide="true">I am not visible.</p>
<p ng-hide="false">I am visible.</p>
</div>
Try it Yourself

AngularJS Events
Previous
Next Chapter
AngularJS has its own HTML events directives.

The ng-click Directive


The ng-click directive defines an AngularJS click event.

AngularJS Example
<div ng-app="" ng-controller="myController">
<button ng-click="count = count + 1">Click me!</button>
<p>{{ count }}</p>
</div>
Try it Yourself

Hiding HTML Elements


The ng-hide directive can be used to set the visibility of a part of an application.

28

The value ng-hide="true" makes an HTML element invisible.


The value ng-hide="false" makes the element visible.

AngularJS Example
<div ng-app="" ng-controller="personController">
<button ng-click="toggle()">Toggle</button>
<p ng-hide="myVar">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</p>
</div>
<script>
function personController($scope) {
$scope.firstName = "John",
$scope.lastName = "Doe"
$scope.myVar = false;
$scope.toggle = function() {
$scope.myVar = !$scope.myVar;
};
}
</script>
Try it Yourself

Application explained:
The first part of the personController is the same as in the chapter about controllers.
The application has a default property (a variable): $scope.myVar = false;
The ng-hide directive sets the visibility, of a <p> element with two input fields,
according to the value (true or false) of myVar.
The function toggle() toggles myVar between true and false.
The value ng-hide="true" makes the element invisible.

Showing HTML Elements


The ng-show directive can also be used to set the visibility of a part of an application.

29

The value ng-show="false" makes an HTML element invisible.


The value ng-show="true" makes the element visible.
Here is the same example as above, using ng-show instead of ng-hide:

AngularJS Example
<div ng-app="" ng-controller="personController">
<button ng-click="toggle()">Toggle</button>
<p ng-show="myVar">
First Name: <input type="text" ng-model="firstName"><br>
Last Name: <input type="text" ng-model="lastName"><br>
<br>
Full Name: {{firstName + " " + lastName}}
</p>
</div>
<script>
function personController($scope) {
$scope.firstName = "John",
$scope.lastName = "Doe"
$scope.myVar = true;
$scope.toggle = function() {
$scope.myVar = !$scope.myVar;
};
}
</script>
Try it Yourself

AngularJS Modules
Previous
Next Chapter
Modules define applications. All application controllers should belong to a module.
Modules make your application more readable, and keep the global namespace clean.

AngularJS Module Example


In this example, "myApp.js" contains an application module definition, "myCtrl.js"
contains a controller:

30

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp"ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>
<script src="myApp.js"></script>
<script src="myCtrl.js"></script>
</body>
</html>
Try it Yourself

Controllers Pollute the Global Namespace


All examples in this tutorial, have used global values (global variables or global
functions).
Global values should be avoided in applications. They can easily be overwritten or
destroyed by other scripts.
AngularJS modules can solve (or reduce) this problem.

A Controller Without a Module


The application does not have a name, and the controller function is global:

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>

31

<body>
<div ng-app=""ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>
<script>
function myCtrl($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
}
</script>
</body>
</html>
Try it Yourself

A Controller With a Module


The application has a name (ng-app="myApp"), and the controller is a property of the
module:

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
</script>

32

</body>
</html>
Try it Yourself

When to Load the Library?


In all our examples, the AngularJS library is loaded in the <head> section.

A common advise for HTML applications, is to place all scripts at the very bottom of the
<body> element.
But, in many AngularJS examples, you will see the library in the < head> element.
This is because calls to angular.module can only be compiled after the library has been
loaded.
Another solution is to load the AngularJS library in the <body> element, but before
your own AngularJS scripts:

AngularJS Example
<!DOCTYPE html>
<html>
<body>
<div ng-app="myApp"ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
</script>
</body>
</html>
Try it Yourself

33

AngularJS Application Files


Now that you know what modules are, and how they work, it is time to build your
application file.
Your application should have at least one module file, and one controller file for each
controller.
First create a module file "myApp.js":
var app = angular.module("myApp", []);
The [] parameter in the module definition can be used to define dependent
modules.
Then create the controller file(s). In this case "myCtrl.js":
app.controller("myCtrl", function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
Finally, edit your HTML page:

AngularJS Example
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-app="myApp"ng-controller="myCtrl">
{{ firstName + " " + lastName }}
</div>
<script src="myApp.js"></script>
<script src="myCtrl.js"></script>
</body>
</html>
Try it Yourself

34

AngularJS Forms
Previous
Next Chapter

An AngularJS form is a collection of input controls.

HTML Controls
HTML input elements are called HTML controls:

input elements
select elements

button elements

textarea elements

HTML Forms
HTML forms group HTML controls together.

An AngularJS Form Example


First Name:
Last Name:

RESET
form = {"firstName":"John","lastName":"Doe"}
master = {"firstName":"John","lastName":"Doe"}

35

Application Code
<div ng-app="" ng-controller="formController">
<formnovalidate>
First Name:<br>
<input type="text" ng-model="user.firstName"><br>
Last Name:<br>
<input type="text" ng-model="user.lastName">
<br><br>
<button ng-click="reset()">RESET</button>
</form>
<p>form = {{user}}</p>
<p>master = {{master}}</p>
</div>
<script>
function formController ($scope) {
$scope.master = {firstName: "John", lastName: "Doe"};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
};
</script>
Try it Yourself

The novalidate attribute is new in HTML5. It disables any default browser


validation.

Example Explained
The ng-app directive defines the AngularJS application.
The ng-controller directive defines the application controller.
The ng-model directive binds two input elements to the user object in the model.
The formController() function sets initial values to themaster object, and invokes the
reset() method.

36

The reset() method sets the user object equal to the master object.
The ng-click directive invokes the reset() method, only if the button is clicked.
The novalidate attribute is not needed for this application, but normally you will use it in
AngularJS forms, to override standard HTML5 validation.

AngularJS Input Validation


Previous
Next Chapter
AngularJS forms and controls can validate input data.

Input Validation
In the previous chapter, you learned about AngularJS forms and controls.
AngularJS forms and controls can provide validation services, and notify users of invalid
input.
Client-side validation cannot alone secure user input. Server side validation is also
necessary.

Application Code
<!DOCTYPE html>
<html>
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<h2>Validation Example</h2>
<form ng-app="" ng-controller="validateCtrl"
name="myForm" novalidate>
<p>Username:<br>
<input type="text" name="user" ng-model="user"required>
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required.</span>

37

</span>
</p>
<p>Email:<br>
<input type="email" name="email" ng-model="email" required>
<spanstyle="color:red" ng-show="myForm.email.$dirty && myForm.email.$invalid">
<span ng-show="myForm.email.$error.required">Email is required.</span>
<span ng-show="myForm.email.$error.email">Invalid email address.</span>
</span>
</p>
<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
myForm.email.$dirty && myForm.email.$invalid">
</p>
</form>
<script>
function validateCtrl($scope) {
$scope.user = 'John Doe';
$scope.email = 'john.doe@gmail.com';
}
</script>
</body>
</html>
Try it Yourself

The HTML form attribute novalidate is used to disable default browser validation.

Example Explained
The AngularJS directive ng-model binds the input elements to the model.
The model object has two properties: user and email.
Because of ng-show, the spans with color:red are displayed only when user or email is
$dirty and $invalid.

AngularJS and Twitter Bootstrap


Previous
Next Chapter
38

Bootstrap is a popular style sheet. This chapter demonstrates how to use it with
AngularJS.

Bootstrap
To include Bootstrap in your AngularJS application, add the following line to your
<head> element:
<link rel="stylesheet"
href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
If you want to study Bootstrap, visit our Bootstrap Tutorial.
Below is a complete HTML example, with all AngularJS directives and Bootstrap classes
explained.

HTML Code
<!DOCTYPE html>
<html ng-app="">
<head>
<link
rel="stylesheet"href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.m
in.css">
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<bodyng-controller="userController">
<div class="container">
<h3>Users</h3>
<tableclass="table table-striped">
<thead><tr>
<th>Edit</th>
<th>First Name</th>
<th>Last Name</th>
</tr></thead>
<tbody><trng-repeat="user in users">
<td>
<button class="btn" ng-click="editUser(user.id)">
<span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;Edit
</button>
</td>
<td>{{ user.fName }}</td>
<td>{{ user.lName }}</td>

39

</tr></tbody>
</table>
<hr>
<button class="btn btn-success"ng-click="editUser('new')">
<span class="glyphicon glyphicon-user"></span> Create New User
</button>
<hr>
<h3 ng-show="edit">Create New User:</h3>
<h3 ng-hide="edit">Edit User:</h3>
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">First Name:</label>
<divclass="col-sm-10">
<input type="text" ng-model="fName" ng-disabled="!edit"placeholder="First Name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Last Name:</label>
<divclass="col-sm-10">
<input type="text" ng-model="lName" ng-disabled="!edit"placeholder="Last Name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Password:</label>
<divclass="col-sm-10">
<input type="password" ng-model="passw1"placeholder="Password">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Repeat:</label>
<divclass="col-sm-10">
<input type="password" ng-model="passw2"placeholder="Repeat Password">
</div>
</div>
</form>
<hr>
<button class="btn btn-success" ng-disabled="error || incomplete">
<span class="glyphicon glyphicon-save"></span> Save Changes
</button>
</div>
<script src = "myUsers.js"></script>
</body>
</html>
Try it Yourself

40

Directives (Used Above) Explained


AngularJS
Directive

Description

<html ng-app

Defines an (unnamed) application for the <html> element

<body ng-controller Defines a controller for the <body> element


<tr ng-repeat

Repeats the <tr> element for each user in users

<button ng-click

Invoke the function editUser() when the <button> element is


clicked

<h3 ng-show

Show the <h3>s element if edit = true

<h3 ng-hide

Hide the <h3> element if edit = true

<input ng-model

Bind the <input> element to the application

<button ng-disabled Disables the <button> element if error or incomplete = true

Bootstrap Classes Explained


Element

Bootstrap Class

Defines

<div>

container

A content container

<table>

table

A table

<table>

table-striped

A striped table

<button>

btn

A button

<button>

btn-success

A success button

<span>

glyphicon

A glyph icon

<span>

glyphicon-pencil

A pencil icon

<span>

glyphicon-user

A user icon

<span>

glyphicon-save

A save icon

<form>

form-horizontal

A horizontal form

<div>

form-group

A form group

<label>

control-label

A control label

41

<label>

col-sm-2

A 2 columns span

<div>

col-sm-10

A 10 columns span

JavaScript Code
function userController($scope) {
$scope.fName = '';
$scope.lName = '';
$scope.passw1 = '';
$scope.passw2 = '';
$scope.users = [
{id:1, fName:'Hege', lName:"Pege" },
{id:2, fName:'Kim', lName:"Pim" },
{id:3, fName:'Sal', lName:"Smith" },
{id:4, fName:'Jack', lName:"Jones" },
{id:5, fName:'John', lName:"Doe" },
{id:6, fName:'Peter', lName:"Pan" }
];
$scope.edit = true;
$scope.error = false;
$scope.incomplete = false;
$scope.editUser = function(id) {
if (id == 'new') {
$scope.edit = true;
$scope.incomplete = true;
$scope.fName = '';
$scope.lName = '';
} else {
$scope.edit = false;
$scope.fName = $scope.users[id-1].fName;
$scope.lName = $scope.users[id-1].lName;
}
};
$scope.$watch('passw1',function() {$scope.test();});
$scope.$watch('passw2',function() {$scope.test();});
$scope.$watch('fName', function() {$scope.test();});
$scope.$watch('lName', function() {$scope.test();});
$scope.test = function() {
if ($scope.passw1 !== $scope.passw2) {
$scope.error = true;
} else {
$scope.error = false;
}
$scope.incomplete = false;
if ($scope.edit && (!$scope.fName.length ||

42

!$scope.lName.length ||
!$scope.passw1.length || !$scope.passw2.length)) {
$scope.incomplete = true;
}
};
}

JavaScript Code Explained


Scope Properties

Used for

$scope.fName

Model variable (user first name)

$scope.lName

Model variable (user last name)

$scope.passw1

Model variable (user password 1)

$scope.passw2

Model variable (user password 2)

$scope.users

Model variable (array of users)

$scope.edit

Set to true when user clicks on create user.

$scope.error

Set to true if passw1 not equal passw2

$scope.incomplete

Set to true if any field is empty (length = 0)

$scope.editUser

Sets model variables

$scope.watch

Watches model variables

$scope.test

Tests model variables for errors and incompleteness

AngularJS Includes
Previous
Next Chapter
With AngularJS, you can include HTML files in HTML.

HTML Includes in Future HTML


Including a portion of HTML in HTML is, unfortunately, not (yet) supported by HTML.

43

HTML imports is a W3C suggestion http://www.w3.org for future versions of HTML:


<link rel="import" href="/path/navigation.html">

Server Side Includes


Most web servers support Server Side Includes (SSI).
With SSI, you can include HTML in HTML before the page is sent to the browser.

PHP Example
<?php require("navigation.php"); ?>

Client Side Includes


There are many ways to use JavaScript to include HTML in HTML.
The most common way, is to use an http request (AJAX) to fetch data from a server,
and then write the data to the innerHTML of an HTML element.

AngularJS Side Includes


With AngularJS, you can include HTML content, using the ng-include directive:

Example
<body>
<divclass="container">
<div ng-include="'myUsers_List.htm'"></div>
<divng-include="'myUsers_Form.htm'"></div>
</div>
</body>
Try it Yourself

Below is a 3 step introduction.

Step 1: Create the HTML List


44

myUsers_List.html
<table class="table table-striped">
<thead><tr>
<th>Edit</th>
<th>First Name</th>
<th>Last Name</th>
</tr></thead>
<tbody><trng-repeat="user in users">
<td>
<button class="btn" ng-click="editUser(user.id)">
<span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;Edit
</button>
</td>
<td>{{ user.fName }}</td>
<td>{{ user.lName }}</td>
</tr></tbody>
</table>
Try it Yourself

Step 2: Create the HTML Form


myUsers_Form.html
<button class="btn btn-success" ng-click="editUser('new')">
<span class="glyphicon glyphicon-user"></span> Create New User
</button>
<hr>
<h3 ng-show="edit">Create New User:</h3>
<h3ng-hide="edit">Edit User:</h3>
<form class="form-horizontal">
<divclass="form-group">
<label class="col-sm-2 control-label">First Name:</label>
<div class="col-sm-10">
<inputtype="text" ng-model="fName" ng-disabled="!edit" placeholder="First Name">
</div>
</div>
<div class="form-group">
<labelclass="col-sm-2 control-label">Last Name:</label>
<divclass="col-sm-10">
<input type="text" ng-model="lName"ng-disabled="!edit" placeholder="Last Name">
</div>
</div>
<divclass="form-group">
<label class="col-sm-2 control-label">Password:</label>
<div class="col-sm-10">
<input type="password" ng-model="passw1" placeholder="Password">
</div>

45

</div>
<div class="form-group">
<label class="col-sm-2 control-label">Repeat:</label>
<div class="col-sm-10">
<input type="password" ng-model="passw2" placeholder="Repeat Password">
</div>
</div>
</form>
<hr>
<button class="btn btn-success"ng-disabled="error || incomplete">
<span class="glyphicon glyphicon-save"></span> Save Changes
</button>
Try it Yourself

Step 3: Create the Main Page


myUsers.html
<!DOCTYPE html>
<html ng-app="">
<head>
<link rel="stylesheet"href =
"http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src=
"http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body ng-controller="userController">
<divclass="container">
<div ng-include="'myUsers_List.htm'"></div>
<divng-include="'myUsers_Form.htm'"></div>
</div>
<script src= "myUsers.js"></script>
</body>
</html>
Try it Yourself

AngularJS Application
Previous
Next Chapter
It is time to create a real AngularJS single page application (SPA).

46

An AngularJS Application Example


You have learned more than enough to create your first AngularJS application:

My Note

SaveClear
Number of characters left: 100

Application Explained
AngularJS Example
<html ng-app="myNoteApp">
<head>
<script
src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
</head>
<body>
<div ng-controller="myNoteCtrl">
<h2>My Note</h2>
<p><textarea ng-model="message" cols="40" rows="10"></textarea></p>
<p>
<button ng_click="save()">Save</button>
<button ng-click="clear()">Clear</button>
</p>

47

<p>Number of characters left: <span ng-bind="left()"></span></p>


</div>
<script src="myNoteApp.js"></script>
<script src="myNoteCtrl.js"></script>
</body>
</html>
Try it Yourself

The application file "myNoteApp.js":


var app = angular.module("myNoteApp", []);
The controller file "myNoteCtrl.js":
app.controller("myNoteCtrl", function($scope) {
$scope.message = "";
$scope.left = function() {return 100 - $scope.message.length;};
$scope.clear = function() {$scope.message = "";};
$scope.save = function() {alert("Note Saved");};
});
The <html> element is the container of the AngularJS application: ngapp="myNoteApp":
<html ng-app="myNoteApp">
A a <div> in the HTML page is the scope of a controller: ng-controller="myNoteCtrl":
<div ng-controller="myNoteCtrl">
An ng-model directive binds a <textarea> to the controller variable message:
<textarea ng-model="message" cols="40" rows="10"></textarea>
The two ng-click events invoke the controller functions clear() and save():
<button ng-click="save()">Save</button>
<button ng-click="clear()">Clear</button>
An ng-bind directive binds the controller function left() to a <span> displaying the
characters left:
Number of characters left: <span ng-bind="left()"></span>
Your application libraries are added to the page (after the library):

48

<script src="myNoteApp.js"></script>
<script src="myNoteCtrl.js"></script>

AngularJS Application Skeleton


Above you have the skeleton (scaffolding) of a real life AngularJS, single page
application (SPA).
The <html> element is the "container" for the AngularJS application (ng-app=).
A <div> elements defines the scope of an AngularJS controller (ng-controller=).
You can have many controllers in one application.
An application file (my...App.js) defines the application module code.
One or more controller files (my...Ctrl.js) defines the controller code.

Summary - How Does it Work?


The AngularJS library is loaded in <head>, because scripts depend on the library code
to be correctly compiled.
The ng-app directive is placed at the root element the application.
For single page applications (SPA), the root of the application is often the < html>
element.
One or more ng-controller directives define the application controllers. Each controller
has its own scope: the HTML element where they were defined.
AngularJS starts automatically on the HTML DOMContentLoaded event. If an ng-app
directive is found, AngularJS will load any module named in the directive, and compile
the DOM with ng-app as the root of the application.
The root of the application can be the whole page, or a smaller portion of the page. The
smaller the portion, the faster the application will compile and execute.

END OF W3SCHOOLS\\\\
49

Table of Contents

AngularJS Hello World


Developing an AngularJS Application From Scratch

AngularJS Application Execution

AngularJS Challenges And Critique

AngularJS is a JavaScript framework that is intended to make it easier to implement RIA


web applications. When I first started learning AngularJS there were not that many
detailed AngularJS tutorials available. That is why I decided to write my own AngularJS
tutorial.
AngularJS is created by Google, which is probably one of the bigger causes of its
success. You can find the AngularJS project here:
http://angularjs.org/
AngularJS is based on the MVC pattern (Model View Control). Therefore AngularJS
separates your RIA application into models, views and controllers. The views are
specified using HTML + AngularJS's own template language. The models and
controllers are specified via JavaScript objects and JavaScript functions. Thus, the
views are specified declaratively, as HTML normally is, and the models and controllers
are specified imperatively, as JavaScript normally is.
If you don't know the difference between declarative and imperative programming, don't
worry. It is not important to know before learning AngularJS. Besides, it is pretty simple
to find the definition on the web.

AngularJS Hello World


50

Here is a simple "hello world" example made with AngularJS which shows the model,
view and controller parts of an AngularJS app:
<!DOCTYPEhtml>
<htmllang="en">

<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="HelloController">

<h2>Hello{{helloTo.title}}!</h2>

</div>

<script>
angular.module("myapp",[])
.controller("HelloController",function($scope){

51

$scope.helloTo={};
$scope.helloTo.title="World,AngularJS";
});
</script>

</body>

</html>

In this example the "view" is this part:


<divngcontroller="HelloController">

<h2>Hello{{helloTo.title}}!</h2>

</div>

Notice the ngcontroller attribute. This attribute tells AngularJS what controller to use
with this view. Notice also the {{helloTo.title}} text. This is part of AngularJS's
template system. This tells AngularJS to write the "model" value
named helloTo.title to the HTML at this location.
The "controller" is this part:
<script>
angular.module("myapp",[])

52

.controller("HelloController",function($scope){
$scope.helloTo={};
$scope.helloTo.title="World,AngularJS";
});
</script>

This code registers a controller function named "HelloController" in the angular module
named "myapp". Angular modules will be explained later in this tutorial.
The $scope parameter passed to the controller function is the "model". The controller
function adds a helloToJavaScript object, and in that object it adds a title field. It is
this helloTo.title value from the model which the view writes into the HTML.

Developing an AngularJS Application From Scratch


Now that you have seen the model, view and controller parts of an AngularJS
application, let us build the above example application from scratch with explanations for
each step.
AngularJS applications are a mix of HTML and JavaScript (as you have already seen)
so the first thing we need is an HTML page:
<!DOCTYPEhtml>
<html>
<head>
</head>

<body>
</body>
</html>

53

Second, we need to include the AngularJS JavaScript file in the HTML page so we can
use AngularJS:
<!DOCTYPEhtml>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<body>
</body>
</html>

Remember to check AngularJS's website for the latest version of AngularJS so you do
not keep using the version I use in this example.
Third, we need to tell AngularJS what part of our HTML page contains the AngularJS
app. You do so by adding thengapp attribute to the root HTML element of the
AngularJS app. Typically, the root element is either the htmlelement or
the body element. In this example I insert the ngapp attribute into the body element:
<!DOCTYPEhtml>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

54

<bodyngapp="myapp">
</body>
</html>

In this example I set the ngapp value to myapp. This means that all controller functions
must be added to the myappmodule. In other words, the AngularJS module
named myapp contains all the controllers for this AngularJS application. The
name myapp is something I have chosen. You can choose your module names freely.
Fourth, we need a view. A view is a section of HTML which is enclosed in an HTML
element. Here is an example:
<!DOCTYPEhtml>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">
<divngcontroller="HelloController">

<h2>Hello{{helloTo.title}}!</h2>

</div>
</body>
</html>

55

In this example the view is the div element and everything inside it. The div element
contains ngcontrollerattribute with the value HelloController. This means, that the
controller function used by this view is namedHelloController.
The view div element contains the HTML
<h2>Hello{{helloTo.title}}!</h2>

This is standard HTML except for the {{helloTo.title}} part. This part tells AngularJS
to insert the model value named helloTo.title into the HTML at that location.
Fifth, we need a controller function. A controller function is a normal JavaScript function
which takes a single parameter: The $scope parameter. The $scope parameter is the
model object to be used by the controller function and the corresponding view. The
controller function can insert data and functions into the model object. The view can
then use the data and the functions.
Here is our little web app with the controller function inserted:
<!DOCTYPEhtml>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">
<divngcontroller="HelloController">

<h2>Hello{{helloTo.title}}!</h2>

56

</div>

<script>
angular.module("myapp",[])
.controller("HelloController",function($scope){
$scope.helloTo={};
$scope.helloTo.title="World,AngularJS";
});
</script>

</body>
</html>

The controller function is registered in angular via


the angular.module(...).controller(...) function call.
The angular object is a global object created by the AngularJS JavaScript which is
included at the beginning of the page.
Notice the first of the parameters to the angular.module() function call. The value of
that parameter is "myapp". This name matches the name specified in the ng
app attribute in the body element. This way AngularJS knows that the controller function
being registered belongs to the myapp module, which happens to be the module which
this AngularJS application is using (specified in the ngapp attribute in
the body element).
The controller() function call is what registers the controller function itself. The first
parameter passed to thecontroller() function is the name of the controller function.
This is the name you refer to in the ngcontrollerattribute of the view. The second
parameter is the controller function itself.
57

AngularJS Application Execution


Now our example application is complete, so let me explain what happens when this
page is loaded into the browser.
First the HTML document is loaded into the browser, and evaluated by the browser. At
this time the AngularJS JavaScript file is loaded, the angular global object is created,
and your JavaScript which registers controller functions is executed.
Second, AngularJS scans through the HTML to look for AngularJS apps and views.
When AngularJS finds a view it connects that view to the corresponding controller
function.
Third, AngularJS executes the controller functions and update (render) the views with
data from the model populated by the controller. The page is now ready.
Fourth, AngularJS listens for browser events (e.g. input fields being changed, buttons
clicked, the mouse moved etc.). If any of these browser events require a view to change,
AngularJS will update the view correspondingly. If the event requires that the
corresponding controller function is called, AngularJS will do that too. Not all events
require the controller function to be called, even if the view is updated as a result of the
event.
That is it. You are now ready to start playing around with your own AngularJS
applications. There is a lot more to learn, but that is covered in subsequent texts in this
AngularJS tutorial (see top left corner of each page in this tutorial series for a list of
topics in the series).

AngularJS Challenges And Critique


Despite AngularJS' success it is not without its challenges. AngularJS makes several
bold claims about AngularJS on its project page. Personally, I believe some of those
claims to be wrong or at least somewhat misguided. It's not like the model used by
AngularJS has not been tried before in other incarnations. That is why I have added
an AngularJS critique to this AngularJS tutorial series. If you decide to go ahead with
AngularJS I would advice you to at least read the critique too. Too many tutorials just
praise AngularJS without looking at its weak spots.
58

Next: AngularJS Views And Directives


Table of Contents

AngularJS Views and Directives Introduction


AngularJS Directives

Interpolation Directive

ng-bind Directive

Escaping HTML From The Model

Conditional Rendering

ng-show + ng-hide Directives

ng-switch Directive

ng-if Directive

ng-include Directive

ng-repeat Directive

Special ng-repeat Variables

Repeating Multiple Elements

Filtering
o

Formatting Filters

Array Filters

Chaining Filters

Assigning Filter Output To Variables

Implementing Custom Filters

AngularJS Views and Directives Introduction

59

In the first text of this tutorial you saw how AngularJS splits an application into views,
controllers and models (MVC). This text will dive deeper into how to create AngularJS
views.
Before we start, let me first set up a simple AngularJS application which you can use to
play around with the examples in this text:
<!DOCTYPEhtml>
<html>
<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="MyController">
<span></span>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
//emptycontrollerfunction
});
</script>

60

</body>
</html>

AngularJS Directives
AngularJS views mix data from the model into an HTML template. You use
AngularJS directives to tell AnguluarJS how to mix the data into the HTML template.
This text will cover the most commonly used AngularJS directives.

Interpolation Directive
The interpolation directive is one of the most fundamental directives in AngujarJS. The
interpolation directive inserts the result of an expression into the HTML template. You
mark where to insert the expression using the {{}} notation. Here is an example:
<divngcontroller="MyController">
<span>{{myData.text}}</span>
</div>

The HTML template is contained within the div element with the ng
controller attribute. Inside the HTML template is a span element, and inside this is an
interpolation directive. This directive instructs AngularJS to insert the data
value myData.text at the given location.
The interpolation directive can also insert data returned from functions of the model
object. Here is an example:
<divngcontroller="MyController">
<span>{{myData.textf()}}</span>
</div>

61

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.textf=function(){return"Atextfromafunction";};
});
</script>

In this example the interpolation directive {{myData.textf()}} will call


the myData.textf() function on the$scope model object, and insert the text returned
from that function into the HTML template.
The textf() function is inserted into the $scope.myData object inside the controller
function, as you can see in the example.

ng-bind Directive
The ngbind directive is an alternative to the interpolation directive. You use it by
inserting an ngbind attribute into the HTML element you want AngularJS to insert data
into. Here is an example:
<divngcontroller="MyController">
<spanngbind="myData.textf()"></span>
</div>

This will insert the data returned from the myData.text() function into the body of
the span element. Notice how the{{}} are not necessary around the expression inside
the ngbind attribute.

Escaping HTML From The Model


62

If the data obtained from the model contains HTML elements, these are escaped before
being inserted into the HTML template. The escaping means that the HTML is displayed
as text, and not as HTML.
This is done to prevent HTML injection attacks. For instance, in a chat application
somebody might insert a <script>element with JavaScript into a chat message. If this
element was not escaped, anyone seeing the chat message might have
the <script> element executed. With the HTML escaping the <script> element will just
be displayed as text.
You can disable the HTML escaping by using the ngbindhtmlunsafe directive, like
this:
<divngcontroller="MyController">
<spanngbindhtmlunsafe="myData.textf()"></span>
</div>

You should be really careful when disabling HTML escaping. Make sure that no HTML is
displayed which is not trusted.

Conditional Rendering
AngularJS can show or hide HTML depending on the state of data in the model. You do
so using a set of AngularJS directives which are created specifically for that purpose. I
will cover these directives in the following sections.

ng-show + ng-hide Directives


The ngshow and nghide directives are used to show or hide an HTML element
depending on data in the model. These two directives do the same thing, but are each
other's opposites. Here are two examples:
<divngcontroller="MyController">
<spanngshow="myData.showIt"></span>

63

<spannghide="myData.showIt"></span>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.showIt=true;
});
</script>

This example creates two span elements. One has an ngshow directive and the other
has an nghide directive. Both directives look at the myData.showIt boolean variable to
determine if they should show or hide the spanelement. The ngshow directive will show
the element if the model value is true, and hide the element if the model value is false.
The nghide directive will do the opposite: Hide the span element if the model value is
true, and show it if the model value is false.
Notice how the controller function sets the myData.showIt to true. This means that the
example above will show the first span element and hide the second.
The HTML elements (span elements in this case) are hidden using the CSS
property display:none;. That means, that the HTML elements are still present in the
DOM. They are just not visible.

ng-switch Directive
The ngswitch directive is used if you want to add or remove HTML elements from the
DOM based on data in the model. Here is an example:
<divngcontroller="MyController">

64

<divngswitchon="myData.switch">
<divngswitchwhen="1">Shownwhenswitchis1</div>
<divngswitchwhen="2">Shownwhenswitchis2</div>
<divngswitchdefault>Shownwhenswitchisanythingelsethan1and
2</div>
</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.switch=3;
});
</script>

This example contains a div element with an ngswitch attribute and an on attribute.
The on attribute tells which data in the model to switch on.
Inside the div element are three nested div elements. The first two nested div elements
contains an ngswitchwhen attribute. The value of this attribute tells what value the
model data referenced in the on attribute of the parentdiv should have, for the
nested div to be visible. In this example the first nested div is visible
whenmyData.switch is 1, and the second nested div is visible when myData.switch is 2.
The third nested div has an ngswitchdefault attribute. If no of the other ngswitch
when directives are matched, then the div with the ngswitchdefault attribute is
shown.

65

In the example above the controller function sets myData.switch to 3. That means that
the nested div with the ngswitchdefault attribute will be shown. The two other
nested div elements will be removed from the DOM completely.

ng-if Directive
The ngif directive can include / remove HTML elements from the DOM, just like
the ngswitch directive, but it has a simpler syntax. Here is an example:
<divngcontroller="MyController">
<divngif="myData.showIt">ngifShowit</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.showIt=true;
});
</script>

The main difference between ngif and ngshow + nghide is that ngif removes the
HTML element completely from the DOM, whereas the ngshow + nghide just applies
the CSS property display:none; to the elements.

ng-include Directive
The nginclude directive can be used to include HTML fragments from other files into
the view's HTML template. Here is an example:

66

<divngcontroller="MyController">
<divnginclude="'angularincludedfragment.html'"></div>
</div>

This example includes the file angularincludedfragment.html into the HTML template
inside the div having the nginclude attribute. Notice how the file name is quoted
(single quotes).
You can include HTML fragments based on conditions. For instance, you can choose
between two files like this:
<divngcontroller="MyController">
<divnginclude="myData.showIt&&
'fragment1.html'||
'fragment2.html'"></div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.showIt=true;
});
</script>

This example will include fragment1.html if myData.showIt is true, and fragment


2.html if myData.showItis false.

67

ng-repeat Directive
The ngrepeat directive is used to iterate over a collection of items and generate HTML
from it. After the initial generation the ngrepeat monitors the items used to generate the
HTML for changes. If an item changes, the ngrepeat directive may update the HTML
accordingly. This includes reordering and removing DOM nodes.
Here is a simple ngrepeat example:
<ol>
<lingrepeat="theIteminmyData.items">{{theItem.text}}</li>
</ol>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.items=[{text:"one"},{text:"two"},{text:
"three"}];
});
</script>

This example will create an li element for each item in the myData.items array.
You can also iterate over collections returned from a function call. Here is an example:
<ol>
<lingrepeat="theIteminmyData.getItems()">{{theItem.text}}</li>
</ol>

68

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.items=[{text:"one"},{text:"two"},{text:
"three"}];
$scope.myData.getItems=function(){returnthis.items;};
});
</script>

And you can iterate over the properties of a JavaScript object using a slightly different
syntax:
<ol>
<lingrepeat="(name,value)inmyData.myObject">{{name}}={{value}}</li>
</ol>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.myObject={var1:"val1",var2:"val3",var3:"val3"};
});
</script>

69

Notice the (name,value) part of the ngrepeat directive. That signals to AngularJS to
iterate over the properties of an object. The name parameter will be bound to the
property name, and the value parameter will be bound to the property value.
The name and value parameters can be output to the HTML template just like any other
JavaScript variable or object property, as you can see from the HTML template above.

Special ng-repeat Variables


The ngrepeat directive defines a set of special variables which you can use when
iterating the collection. These variables are:

$index
$first

$middle

$last

The $index variable contains the index of the element being iterated.
The $first, $middle and $last contain a boolean value depending on whether the
current item is the first, middle or last element in the collection being iterated. An item is
"middle" if it is not first nor last. You can use these variables to generate different HTML
using e.g. the ngshow / nghide, ngswitch, ngif and nginclude directives described
earlier.

Repeating Multiple Elements


So far you have only seen how to repeat a single HTML element using ngrepeat. In
case you want to repeat more than one HTML element you would have to nest those
elements inside a container element, and have the container element have the ng
repeat element, like this:
<divngrepeat="(name,value)inmyData.myObject">
<div>{{name}}</li>
<div>{{value}}</li>

70

</div>

Wrapping the element to be repeated in a root element may not always be possible
though. Therefore AngularJS has the ngrepeatstart and ngrepeatend directives
which mark which element to start and end the repetition with. Here is an example:
<ol>
<lingrepeatstart="(name,value)inmyData.myObject">{{name}}</li>
<lingrepeatend>{{value}}</li>
</ol>

This example will repeat both of the li elements for each property in myData.myObject.

Filtering
Some of the directives covered above support filtering. This section will explain how
filtering works.
The ngrepeat directive can accept a filter like this:
<divngrepeat="iteminmyData.items|filter:itemFilter"></div>

Notice the |filter:itemFilter part of the declaration above. That part is the filter
definition. The |filter:part tells AngularJS to apply a filter to the myData.items array.
The itemFilter is the name of the filter function. This function has to be present on
the $scope object, and it has to return either true or false. If the filter function returns
true, then the element from the array is used by the ngrepeat directive. If the filter
function returns false, the element is ignored. Here is an example:
<script>
angular.module("myapp",[])
.controller("MyController",function($scope){

71

$scope.myData={};
$scope.myData.items=[{text:"one"},{text:"two"},{text:"three"},
{text:"four"}];

$scope.itemFilter=function(item){
if(item.text=="two")returnfalse;
returntrue;
}
}
});
</script>

Formatting Filters
AngularJS comes with a set of built-in formatting filters which can be used in conjunction
with the interpolation directive, and with ngbind. Here is a list of the formatting filters:

Filter

Description

date

Formats the variable as a date according to the given


date format

currency

Formats the variable as a number with a currency


symbol

72

number

Formats the variable as a number

lowercase Converts the variable to lowercase

uppercase Converts the variable to uppercase

json

Converts the variable to a JSON string

Here is a date filter example:


<span>{{myData.theDate|date:'ddMMyyyy'}}</span>

This example shows the date filter which can format a JavaScript date object according
to the date format pattern given after the |date:part. It is the myData.theDate property
that will be formatted as a date. Thus, it has to be a JavaScript date object.
Here is a number filter example:
<span>{{myData.theNumber|number:2}}</span>

This example formats the myData.theNumber variable as a number with 2 decimal


places.
Here are an lowercase and uppercase filter example:
<span>{{myData.mixedCaseText|lowercase}}</span>
<span>{{myData.mixedCaseText|uppercase}}</span>

73

Array Filters
AngularJS also contains a set of array filters which filters or transforms arrays. These
filters are:
Array Filters:

Filter

Description

limitTo Limits the array to the given size, beginning from some index in the array.
The limitTo filter also works on strings.

filter

A general purpose filter.

orderBy Sorts the array based on provided criteria.

Here is a limitTo example:


<span>{{myData.theText|limitTo:3}}</span>

This limits the $scope myData.theText variable to a length of 3 characters. If this filter
had been applied to an array, the array would have been limited to 3 elements.
The filter filter is a special filter which can do a lot of different things. In its simplest
form it simply calls a function on the $scope object. This function must
return true or false. True is returned if the filter accepts the value passed to it. False is
returned if the filter cannot accept the value. If the filter cannot accept the value, the
value is not included in the array resulting from the filtering. Here is an example:
74

<ol>
<lingrepeat="iteminmyData.items|filter:filterArray">
{{item.text}}:{{$first}},{{$middle}},{{$last}}
</li>
</ol>
<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.items=
[{text:"one"},{text:"two"},{text:"three"},{text:
"four"}];

$scope.filterArray=function(item){
if(item.text=="two")returnfalse;
returntrue;
}
});
</script>

This example calls the filterArray() function which filters out items which has
a text property with the value two.
Here is an orderBy example:
<ol>
<lingrepeat="iteminmyData.items|orderBy:sortField:reverse">

75

{{item.text}}:{{$first}},{{$middle}},{{$last}}
</li>
</ol>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.items=[{text:"one"},{text:"two"},{text:
"three"},{text:"four"}];
$scope.sortField="text";
$scope.reverse=true;
});
</script>

The orderBy filter takes a $scope variable as parameter. In this example that variable is
named sortField. The value of this variable is the name of the property on the sorted
data objects which is used to sort the data objects. In this example
the sortField property is set to text which means that the data object's text property is
used to sort the data objects.
The orderBy filter can also take a second $scope variable as parameter. In this example
that variable is namedreverse. The value of this variable determines if the data objects
are to be sorted in their natural order, or the reverse order of that. In this case
the reverse variable is set to true, meaning the data objects will be sorted in reverse
order.

76

Chaining Filters
It is possible to chain filters by simply putting more filters after each other in the filter
section. When chaining filters, the output of one filter is used as input for the next filter in
the chain. Here is an example:
<span>{{myData.theText|limitTo:5|uppercase}}</span>

This example first limits the string myData.theText to 5 characters using


the limitTo filter, and the converts the 5 characters to uppercase using
the uppercase filter.

Assigning Filter Output To Variables


It is possible to assign the output of a filter to a temporary variable which you can then
refer to later in your view. Here is an example:
<ol>
<lingrepeat="iteminfilteredItems=(myData.items|filter:filterArray)">
{{item.text}}:{{$first}},{{$middle}},{{$last}}
</li>
</ol>
<div>{{filteredItems.length}}</div>

This example assigns the output of the filtering to the filteredItems variable. The
example then refers to this variable inside the {{}} directive under the ol element.

Implementing Custom Filters


You can implement your own filters in case the AngularJS filters do not suit your needs.
Here is an example:

77

<div>Filtered:{{myData.text|myFilter}}</div>

<script>
varmodule=angular.module("myapp",[]);

module.filter('myFilter',function(){

returnfunction(stringValue){
returnstringValue.substring(0,3);
};
});
</script>

This example registers a filter with AngularJS which can filter strings. The filter returns
the first 3 characters of the string. The filter is registered with the name myFilter. It is
this name you will have to use when referencing the filter, as you can see in the
beginning of the filter.
If your filter needs more input parameters, add more parameters to the filter function,
and add the parameters after the filter name and a : when referencing it. Here is an
example:
<div>Filtered:{{myData.text|myFilter:2:5}}</div>

<script>
varmodule=angular.module("myapp",[]);

78

module.filter('myFilter',function(){

returnfunction(stringValue,startIndex,endIndex){
returnstringValue.substring(parseInt(startIndex),
parseInt(endIndex));
};
});
</script>

Notice how the filter reference (|myfilter:2:5) now has two values after the filter
name, each value separated by a colon. These two values are passed to the filter as
parameters. Notice also how the filter function now takes two extra parameters
named startIndex and endIndex. These two parameters are used to determine which
part of the string to return as substring from the filter.

Next: AngularJS $scope Hierarchy


The $scope object used by views in AngularJS are organized into a hierarchy. There is a
root scope, and the root scope has one or more child scopes. Each view has its
own $scope (which is a child of the root scope), so whatever variables one view
controller sets on its $scope variable, those variables are invisible to other controllers.
Look at this AngularJS code example:
<!DOCTYPEhtml>
<htmllang="en">

<head>

79

<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="myController1">

{{data.theVar}}

</div>

<divngcontroller="myController2">

{{data.theVar}}

</div>

<script>
varmodule=angular.module("myapp",[]);
varmyController1=module.controller("myController1",function($scope){
$scope.data={theVar:"ValueOne"};
});

80

varmyController2=module.controller("myController2",function($scope){
$scope.data={theVar:"ValueTwo"};
});
</script>

</body>
</html>

This example contains two views, each with their own controller function. Each controller
sets the variabledata.theVar to different values.
When this example is executed, the $scope hierarchy will look like this:

Root $scope
o $scope for myController 1
o

$scope for myController 2

As you can see, the $scope object used by the two controllers are not the
same $scope object. That is also why the example above would write out two different
values for the data bindings {{data.theVar}} inside the two views. The two controller
functions for the views set different values for the data.theVar variable in each their
own $scopeobject.

Next: AngularJS Events


Table of Contents

AngularJS Event Handling Introduction


AngularJS Event Listener Directives
81

AngularJS Event Listener Examples

AngularJS Event Handling Introduction


When creating more advanced AngularJS applications, sooner or later your application
will need to handle DOM events like mouse clicks, moves, keyboard presses, change
events etc. AngularJS has a simple model for how to add event listeners to the HTML
you generate from your views. This text will explain this model.
Before we dive into the event stuff let me just show you a simple AngularJS application
which we will use as base for the examples shown in this text:
<!DOCTYPEhtml>
<htmllang="en">

<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="MyController">
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){

82

$scope.myData={};
});
</script>

</body>
</html>

AngularJS Event Listener Directives


You attach an event listener to an HTML element using one of the AngularJS event
listener directives:

ngclick
ngdblclick

ngmousedown

ngmouseup

ngmouseenter

ngmouseleave

ngmousemove

ngmouseover

ngkeydown

ngkeyup

ngkeypress

ngchange

AngularJS Event Listener Examples


Here is a simple AngularJS event listener directive example:
83

<divngcontroller="MyController">
<divngclick="myData.doClick()">Clickhere</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.doClick=function(){
alert("clicked");
}
});
</script>

When you click the inner div of the above example, the myData.doClick() function will
get called. As you can see in the controller function, the myData object has
a doClick() function added to it.
As you can see, attaching events to HTML DOM elements is not much different from
generating the HTML in the first place. The event listener functions called are functions
added to the $scope object by the controller function.
The event listener directives have a special variable named $event which you can use
as parameter to the event listener function. The $event variable contains the original
browser event object. Here is an example:
<divngcontroller="MyController">
<divngclick="myData.doClick($event)">Clickhere</div>
</div>

84

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};
$scope.myData.doClick=function(event){
alert("clicked:"+event.clientX+","+event.clientY);
}
});
</script>

You can also pass other parameters to your event listener functions. Here is an example
that adds event listener function to a list of li elements:
<divngcontroller="MyController">
<ul>
<lingrepeat="iteminmyData.items"
ngclick="myData.doClick(item,$event)">Clickhere</li>
</ul>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myData={};

85

$scope.myData.items=[{v:"1"},{v:"2"},{v:"3"}];

$scope.myData.doClick=function(item,event){
alert("clicked:"+item.v+"@"+event.clientX+":"+
event.clientY);
}

});
</script>

This example iterates through a list of items, generates li elements from them, and
adds click listeners to each lielement. Along with the call to the click listener is passed
the item JavaScript object the li element was generated based on, along with the click
event object ($event).

Next: AngularJS $watch() , $digest() and $apply()


Table of Contents

$watch()
$digest()

$apply()

Example

The AngularJS $scope functions $watch(), $digest() and $apply() are some of the
central functions in AngularJS. Understanding $watch(), $digest() and $apply() is
essential in order to understand AngularJS.

86

When you create a data binding from somewhere in your view to a variable on
the $scope object, AngularJS creates a "watch" internally. A watch means that
AngularJS watches changes in the variable on the $scope object. The framework is
"watching" the variable. Watches are created using the $scope.$watch() function which
I will cover later in this text.
At key points in your application AngularJS calls the $scope.$digest() function. This
function iterates through all watches and checks if any of the watched variables have
changed. If a watched variable has changed, a corresponding listener function is called.
The listener function does whatever work it needs to do, for instance changing an HTML
text to reflect the new value of the watched variable. Thus, the $digest() function is
what triggers the data binding to update.
Most of the time AngularJS will call the $scope.$watch() and $scope.
$digest() functions for you, but in some situations you may have to call them yourself.
Therefore it is really good to know how they work.
The $scope.$apply() function is used to execute some code, and then call $scope.
$digest() after that, so all watches are checked and the corresponding watch listener
functions are called. The $apply() function is useful when integrating AngularJS with
other code.
I will get into more detail about the $watch(), $digest() and $apply() functions in the
remainder of this text.

$watch()
The $scope.watch() function creates a watch of some variable. When you register a
watch you pass two functions as parameters to the $watch() function:

A value function
A listener function

Here is an example:
$scope.$watch(function(){},
function(){}

87

);

The first function is the value function and the second function is the listener function.
The value function should return the value which is being watched. AngularJS can then
check the value returned against the value the watch function returned the last time.
That way AngularJS can determine if the value has changed. Here is an example:
$scope.$watch(function(scope){returnscope.data.myVar},
function(){}
);

This example valule function returns the $scope variable scope.data.myVar. If the value
of this variable changes, a different value will be returned, and AngularJS will call the
listener function.
Notice how the value function takes the scope as parameter (without the $ in the name).
Via this parameter the value function can access the $scope and its variables. The value
function can also watch global variables instead if you need that, but most often you will
watch a $scope variable.
The listener function should do whatever it needs to do if the value has changed.
Perhaps you need to change the content of another variable, or set the content of an
HTML element or something. Here is an example:
$scope.$watch(function(scope){returnscope.data.myVar},
function(newValue,oldValue){
document.getElementById("").innerHTML=
""+newValue+"";
}
);

88

This example sets the inner HTML of an HTML element to the new value of the variable,
embedded in the b element which makes the value bold. Of course you could have done
this using the code {{data.myVar}, but this is just an example of what you can do
inside the listener function.

$digest()
The $scope.$digest() function iterates through all the watches in the $scope object,
and its child $scope objects (if it has any). When $digest() iterates over the watches, it
calls the value function for each watch. If the value returned by the value function is
different than the value it returned the last time it was called, the listener function for that
watch is called.
The $digest() function is called whenever AngularJS thinks it is necessary. For
instance, after a button click handler has been executed, or after an AJAX call returns
(after the done() / fail() callback function has been executed).
You may encounter some corner cases where AngularJS does not call
the $digest() function for you. You will usually detect that by noticing that the data
bindings do not upate the displayed values. In that case, call $scope.$digest() and it
should work. Or, you can perhaps use $scope.$apply() instead which I will explain in
the next section.

$apply()
The $scope.$apply() function takes a function as parameter which is executed, and
after that $scope.$digest()is called internally. That makes it easier for you to make sure
that all watches are checked, and thus all data bindings refreshed. Here is
an $apply() example:
$scope.$apply(function(){
$scope.data.myVar="Anothervalue";
});

89

The function passed to the $apply() function as parameter will change the value
of $scope.data.myVar. When the function exits AngularJS will call the $scope.
$digest() function so all watches are checked for changes in the watched values.

Example
To illustrate how $watch(), $digest() and $apply() works, look at this example:
<divngcontroller="myController">
{{data.time}}

<br/>
<buttonngclick="updateTime()">updatetimengclick</button>
<buttonid="updateTimeButton">updatetime</button>
</div>

<script>
varmodule=angular.module("myapp",[]);
varmyController1=module.controller("myController",function($scope){

$scope.data={time:newDate()};

$scope.updateTime=function(){
$scope.data.time=newDate();
}

90

document.getElementById("updateTimeButton")
.addEventListener('click',function(){
console.log("updatetimeclicked");
$scope.data.time=newDate();
});
});
</script>

This example binds the $scope.data.time variable to an interpolation directive which


merges the variable value into the HTML page. This binding creates a watch internally
on the $scope.data.time variable.
The example also contains two buttons. The first button has an ngclick listener
attached to it. When that button is clicked the $scope.updateTime() function is called,
and after that AngularJS calls $scope.$digest() so that data bindings are updated.
The second button gets a standard JavaScript event listener attached to it from inside
the controller function. When the second button is clicked that listener function is
executed. As you can see, the listener functions for both buttons do almost the same,
but when the second button's listener function is called, the data binding is not updated.
That is because the $scope.$digest() is not called after the second button's event
listener is executed. Thus, if you click the second button the time is updated in
the $scope.data.time variable, but the new time is never displayed.
To fix that we can add a $scope.$digest() call to the last line of the button event
listener, like this:
document.getElementById("updateTimeButton")
.addEventListener('click',function(){
console.log("updatetimeclicked");

91

$scope.data.time=newDate();
$scope.$digest();
});

Instead of calling $digest() inside the button listener function you could also have used
the $apply() function like this:
document.getElementById("updateTimeButton")
.addEventListener('click',function(){
$scope.$apply(function(){
console.log("updatetimeclicked");
$scope.data.time=newDate();
});
});

Notice how the $scope.$apply() function is called from inside the button event listener,
and how the update of the$scope.data.time variable is performed inside the function
passed as parameter to the $apply() function. When the $apply() function call finishes
AngularJS calls $digest() internally, so all data bindings are updated.

Next: AngularJS AJAX


Table of Contents

AngularJS AJAX Introduction


The $http Service
o

$http Functions
92

$http as a Function

The config Parameter

The success() And error() Functions of The Promise Object

AngularJS & JSONP


o

JSONP Security

AngularJS AJAX Introduction


In AngularJS you can send AJAX requests in several different ways. These are:

AJAX calls via the $http service.


JSONP calls via the $http service.

REST type calls.

Note: So far only the $http service is covered (both normal AJAX and JSONP), but that
is enough to get you started using AJAX in AngularJS. The REST API is not necessary
to understand to start using AJAX (and personally I am not that big a fan of it - you can
do the same just as easily with the $http service).

The $http Service


The $http service is the easiest way to send AJAX calls to your web server. Remember,
that AJAX calls cannot be sent to a different domain than the domain from which the
HTML page making the AJAX calls is loaded. For instance, if the HTML page was
loaded from jenkov.com then that HTML page can only make AJAX calls back to URLs
within the jenkov.com domain.
Here is a full AngularJS application with a single $http AJAX example:
<!DOCTYPEhtml>
<htmllang="en">

93

<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="MyController">
<buttonngclick="myData.doClick(item,$event)">SendAJAXRequest</button>
<br/>
Datafromserver:{{myData.fromServer}}
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope,$http){
$scope.myData={};
$scope.myData.doClick=function(item,event){

varresponsePromise=$http.get("/angularjsexamples/jsontest
data.jsp");

responsePromise.success(function(data,status,headers,config){
$scope.myData.fromServer=data.title;
});

94

responsePromise.error(function(data,status,headers,config){
alert("AJAXfailed!");
});
}

});
</script>

</body>

</html>

Notice how the controller function registered with the module takes two parameters:
A $scope object (as always) and an extra $http object. The $http object (or "service") is
used to make AJAX calls.
The the $http.get() function returns a "promise" object. This promise object has
a success() and an error()function. By calling these functions and pass a function to
them as parameter you can control what happens when the AJAX call finishes. If the
AJAX call succeeds (the server sends back an HTTP code between 200 and 209), the
function passed to the success() function is executed. If the AJAX call fails (all other
codes except for redirects), the function passed to the error() method is executed.
The succss() and error() functions are covered in more detail later.

$http Functions
The $http service has several functions you can use to send AJAX requests. These are:

$http.get(url,config)
$http.post(url,data,config)
95

$http.put(url,data,config)

$http.delete(url,config)

$http.head(url,config)

Notice that the $http.post() and $http.put() functions take a data parameter which
contains data to be sent to the server. The rest of the $http functions cannot take a data
parameter.
The data parameter will be converted to a JSON string. This string will be be included in
the request body when the HTTP request is sent to the server. AngularJS will consider
all properties starting with a $ as private, and thus exclude these from the string. If you
need to include properties starting with a $ in the data string, convert the data object to
a string yourself using JSON.stringify(data).

$http as a Function
You can also use the $http service as a function directly, like this:
varpromise=$http(config);

In this case the URL and HTTP method are also set inside the config object.
The config object is explained in the following section.

The config Parameter


The config parameter passed to the different $http functions controls the HTTP request
sent to the server. Theconfig parameter is a JavaScript object which can contain the
following properties:

method
url

params

headers

timeout
96

cache

transformRequest

transformResponse

The method property can be used to set the HTTP method for pthe request. The method
is one of either GET,POST,PUT,DELETE or HEAD. This property is normally set implicitly
via the function you choose to call on the $httpservice, so you will rarely need to set this
property in practice.
The url property can be used to set the URL of the AJAX call. This is already provided
to the various $http functions, so you will rarely need to set this again in
the config object.
The params property is used to set any additional request parameters to be appended to
the URL query string. Theparams property is a JavaScript object with one property per
request parameter to add.
The headers property is used to set any additional HTTP headers you want sent to the
server. The headers property is a JavaScript object with one property per header.
The timeout property is used to set the timeout for the AJAX call. When the timeout limit
is reached, the AJAX call is aborted. The timeout is specified in milliseconds.
The cache property is used to enable XHR GET request caching.
The transformRequest property is used to set a function which can transform the
request object before it is sent to the server.
The transformResponse property is used to set a function which can transform the
response sent back from the server, before it is passed to your application.

The success() And error() Functions of The Promise Object


As mentioned earlier the various AJAX functions on the $http service return a promise
object. This promise object has two functions called success() and error(). Each of
these two functions take a callback function as parameter. If the AJAX request
succeeds, the callback function passed to the success() function is executed. If the
AJAX request fails, the callback function passed to the error() function is called.
97

Inside the success() and error() function you should set the appropriate values on
the $scope object. That is the way to get the data or error message out to the user.
Update the $scope object with data, and AngularJS will trigger the HTML template
rendering so the data can be made visible to the user.
Both functions take the following parameters:

data
status

headers

config

The data parameter is the JSON object returned by the server. The $http service
assumes that your server sends back JSON.
The status parameter is the HTTP status code returned by the server along with the
response.
The headers parameter is a function that can be used to obtain any HTTP response
headers returned along with the response. You get a header by
calling headers([headerName]);. As you can see, the headers() function take an array
of header names as parameter. The AngularJS documentation is a bit vague about what
the function returns, but I suspect it returns a JavaScript object with one key, value pair
for each header, with the header name as the key (property name).
The config parameter is the configuration object that was used to create the given
HTTP request (AJAX call). In other words, the config object which was passed as
parameter to the $http ajax function call that created this AJAX call, and thereby this
promise object.

AngularJS & JSONP


AngularJS's $http service is also capable of sending JSONP requests. The normal
AJAX calls can only send requests to URLs within the same domain as the HTML page
sending the requests was loaded from. You can get around this with JSONP requests.

98

JSONP is short for "JSON with Padding" (I explain why, later). A JSONP request is not
sent via the XHR object like AJAX calls normally are. Instead, a <script> element is
created and inserted into the HTML page. Here is an example of how such
a <script> element could look:
<scriptsrc="http://jenkov.com/theService.json?
callback=theServiceResponse&p1=v1&p2=v2"></script>

The src attribute contains the URL of the remote service to call with the JSONP call.
This URL should include any parameters you need to send to the remote service.
When the <script> element is inserted into the HTML page, the browser will load the
script from the given URL. That enables the remote service to send JavaScript back to
your application for execution.
The JavaScript returned by the remote service should be a function call to an existing
JavaScript function in your HTML page. Here is how the returned JavaScript could look:
theServiceResponse({name:"John",title:"CEO",company:"BigFatCo"});

This code makes a function call to the function named theServiceResponse. This
function must be present in your HTML page already. Inside this function you process
the response sent back from the service.
When the theServiceResponse() function is called, a JavaScript object is passed to the
function as parameter. This JavaScript object contains the response parameters from
the service call. Thus, this JavaScript object is generated by the remote service.
Whatever the remote service wants to send back to you is what this JavaScript object
contains. Seen from the remote service's perspective, that JavaScript object is just
JSON like any other JSON sent back to an HTML page. The difference is that this JSON
object is wrapped in a function call. This function call is the "padding" part of the "JSON
with Padding" name for JSONP.
You might wonder how the remote service knows the name of the function to wrap the
returned JSON in. The answer is, that you pass that name to the remote service along
with the other request parameters. The function name is one of the request parameters.

99

By default this parameter name is callback but you will have to check with the concrete
service to see what parameter name it expects for the function name.
In AngularJS the function name is supplied behind the scene by AngularJS, so you don't
have to worry about adding it to the URL of the remote service.
You use JSONP calls via the $http service like this:
$http.jsonp(url,config);

Like with the AJAX functions the jsonp() function takes a url and a config object. Here
is an example of a JSONP call with the url and config objects supplied:
varurl=http://jenkov.com/theService.json?callback=JSON_CALLBACK";
varresponsePromise=$http.jsonp(url,
{params:{
p1:"v1"
,p2:"v2"
}
}
);

responsePromise.success(function(data){
//dosomethingwiththereturnedJavaScriptobject
//(inthe"data"parameter).
});

This example makes a JSONP call to the service


URL http://jenkov.com/theService.json. Like with the other AJAX functions of
100

the $http service, the config object can contain a params field. This field should be a
JavaScript object containing all the request parameters to append to the URL of the
remote service.
When you call the $http.jsonp() function AngularJS will create <script> element for
you, and insert it into your HTML page. AngularJS will also create the final URL of the
remote service by appending the parameters passed in the config.params object to the
URL.
The URL passed to the $http.jsonp() function must contain
the callback=JSON_CALLBACK parameter. AngularJS will replace the JSONCALLBACK string
with the name of a callback function which AngularJS creates.
The promise object returned by the $http.jsonp() function has a success() function,
just like the other AJAX function call promise objects. Unfortunately we do not have
access to the HTTP headers of the response sent back from the server, since that
request is handled by the browser internally, when evaluating the <script
src="url">element. That also means that if the JSONP call fails, we have no way of
knowing so, since no callback function will get called in that case (no JavaScript to
execute from the remote service).

JSONP Security
You have to be careful with JSONP calls. When you make a JSONP call. The remote
service could send back anyJavaScript which would then get executed inside your
HTML page. An evil remote service could send back JavaScript which attempts to steal
information from your application and sent it to a third party service. Only make JSONP
calls to services you trust.

Next: AngularJS Forms


Table of Contents

AngularJS Form Handling Introduction


101

Binding Checkboxes

Binding Radio Buttons

Binding Select Boxes


o

ng-options

Empty Options

Selecting Multiple Options

Form Validation

ng-minlength + ng-maxlength

ng-pattern

ng-required

Checking Field Validation State

Submitting Forms

AngularJS Form Handling Introduction


AngularJS has some features for binding data of HTML form input fields to the model
object ($scope). These features makes it easier to work with forms.
You bind an input field to a model property using the ngmodel directive like this:
<inputtype="text"id="firstName"ngmodel="myForm.firstName">

This binding is two-way, meaning if the $scope.myForm.firstName has a value set inside
the corresponding controller function, the input field will start with that value.
Additionally, once the user types something into the text field, that value will be copied
from the text field into the $scope.myForm.firstName property.
Here is a full AngularJS form example you can play with:
<!DOCTYPEhtml>
<html>

102

<head>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
</head>

<bodyngapp="myapp">

<divngcontroller="MyController">
<form>
<inputtype="text"name="firstName"ngmodel="myForm.firstName">First
name<br/>
<inputtype="text"name="lastName"ngmodel="myForm.lastName">Lastname
<br/>
</form>

<div>
{{myForm.firstName}}{{myForm.lastName}}
</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myForm={};
$scope.myForm.firstName="Jakob";

103

$scope.myForm.lastName="Jenkov";
});
</script>

</body>
</html>

This example binds the two input fields in the form to


the $scope.myForm.firstName and$scope.myForm.lastName properties. The two
properties both have a value set in the controller function. These values will be
displayed in the input fields when the page is first rendered. When the user types in
something in the text fields it will get copied into the these properties too.
The example also contains two interpolation directives ( {{}}). These two directives will
insert the value of themyForm.firstName and myForm.lastName below the form fields.
When you enter something in the text boxes it will be copied into
the myForm.firstName and myForm.lastName properties. From there it will be inserted
into the HTML by the two interpolation directives. This data binding happens while the
user enters data in the form fields, so the interpolation directives will update the values
while typing (this looks cool, but I cannot remember the last time I actually needed this
in a web app form).

Binding Checkboxes
If you bind a checkbox (<inputtype="checkbox">) to a model property, the model
property will be set to true if the checkbox is checked, and false if not.
If you need other values instead of true and false inserted into your model, you can
use the ngtruevalue andngfalsevalue directives, like this:
<inputtype="checkbox"ngmodel="myForm.wantNewsletter"
ngtruevalue="yes"ngfalsevalue="no">

104

Binding Radio Buttons


Radio buttons are also easy to bind to model properties. If you have a group of radio
buttons, just bind them all to the same model property. The radio button that is chosen
will have its value copied into the model property. Here is an example:
<inputtype="radio"ngmodel="myForm.whichNewsletter"value="weeklyNews">
<inputtype="radio"ngmodel="myForm.whichNewsletter"value="monthlyNews">

Binding Select Boxes


Binding select boxes to model properties is reasonably straightforward too. Here is an
example:
<divngcontroller="MyController">
<form>
<selectngmodel="myForm.car">
<optionvalue="nissan">Nissan</option>
<optionvalue="toyota">Toyota</option>
<optionvalue="fiat">Fiat</option>
</select>
</form>

<div>
{{myForm.car}}
</div>
</div>

105

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myForm={};
$scope.myForm.car="nissan";
});
</script>

ng-options
Instead of using static HTML options you can have AngularJS create option elements
based on data from the $scopeobject. You do so using the ngoptions directive inside
the select element. Here is an example:
<divngcontroller="MyController">
<form>
<selectngmodel="myForm.car"
ngoptions="obj.idasobj.nameforobjinmyForm.options">
</select>
</form>

<div>
{{myForm.car}}
</div>
</div>

106

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myForm={};
$scope.myForm.car="nissan";

$scope.myForm.options=[
{id:"nissan",name:"Nissan"}
,{id:"toyota",name:"Toyota"}
,{id:"fiat",name:"Fiat"}
];

});
</script>

The ngoptions directive follows the following format:


optionBindingexpressiondataSourceexpression

The dataSourceexpression speficies what data in the $scope object is to be used as


data source for the optionelements. In the example above, the dataSource
expression is this part:
forobjinmyForm.options

It defines obj as each object in the myForm.options array. Thus, an option element will
be generated from each element in the myForm.options array in the $scope object.

107

The optionBindingexpression specifies what properties are to be used as value and


label for each optionelement. In the example above the optionBinding is this part:
obj.idasobj.name

This defines the obj.id property of each object as the value of each option element
generated, and the obj.nameproperty as the label. If you want the value and label to
come from the same property, just leave out the asobj.name part (the label part of the
expression).
You can call functions on the $scope object from inside both the optionBinding
expression and dataSourceexpression. Here is an example:
obj.idasgetLabelName(obj)forobjingetOptionArray()

This example will use the value returned from the getLabelName(obj) function call as
label, and will iterate the objects returned by the getOptionArray() function call.
You can create option groups ( <optgroup> HTML elements with option elements
inside) by adding a groupbysection to the optionBinding expression. Here is an
example:
obj.idasobj.namegroupbyobj.type

This example will group the generated option elements into optgroup elements using
the obj.type property to determine which option elements to group together. Objects
with the same value in the obj.type property will be grouped into the
same optgroup element.
You can also iterate the properties of an object instead of iterating an array of objects.
Here is an example:
propNameaspropValuefor(propName,propValue)inobjectWithProperties

This example will bind the property name as the option element value and the property
value as the label, of all properties in the $scope.objectWithProperties object.
108

Empty Options
If the value set for a select box in the $scope object by the controller function does not
match a value attribute of any of the option elements, AngularJS inserts an
empty option element in the select box.
You can set a label for this empty option element by inserting an option element in the
HTML, like this:
<form>
<selectngmodel="myForm.car"
ngoptions="obj.idasobj.nameforobjinmyForm.options">
<optionvalue="">Pleasechooseacar</option>
</select>
</form>

Selecting Multiple Options


If you need a select box that enables the user to choose multiple options, you need to
insert the multiple="true"attribute inside the <select> element.
Once you enable multiple option selection, the data binding changes. Instead of binding
the <select> element to a single string value, it is now bound to an array of values.
Thus, you also set the selected values using an array. Here is an example showing that:
<divngcontroller="MyController">
<form>
<selectmultiple="true"ngmodel="myForm.car"
ngoptions="obj.idasobj.nameforobjinmyForm.options">
</select>
</form>

109

<div>
{{myForm.car}}
</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myForm={};
$scope.myForm.car=["nissan"];

$scope.myForm.options=[
{id:"nissan",name:"Nissan"}
,{id:"toyota",name:"Toyota"}
,{id:"fiat",name:"Fiat"}
];

});
</script>

Form Validation
AngularJS has a set of form validation directives you can use. AngularJS validates form
fields before copying their value into the $scope properties to which the form fields are
bound. If a form field is invalid, its value is not copied into the $scope property it is bound
110

to. Instead the corresponding $scope property is cleared. That is done to prevent
the$scope properties from containing invalid values.
Each of the form validating directives are covered in the following sections.

ng-minlength + ng-maxlength
The ngminlength and ngmaxlength form validation directives can be used to validate
the length of data entered in a form field. Here is an example:
<divngcontroller="MyController">
<form>
<inputtype="text"id="name"ngmodel="myForm.name"ngminlength="5"ng
maxlength="12">Name<br/>
</form>

<div>
{{myForm.name}}
</div>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope){
$scope.myForm={};
$scope.myForm.name="JakobJenkov";
});
</script>

111

This example sets the ngminglength to 5 and ngmaxlength to 12. That means that if
the text in the input field is less than 5 or more than 12 characters long, the value from
the input field will not be copied into the $scope.myForm.name property. You can try this
example yourself and see what happens.
Notice the div element which displays the value of the $scope.myForm.name. This wil
show you what value was copied from the text field into
the $scope.myForm.name property. Notice how it is empty when the text field contains
less than 5 or more than 12 characters.

ng-pattern
The ngpattern directive can be used to validate the value of an input field against a
regular expression. Here is an example:
<inputtype="text"id="name"ngmodel="myForm.name"ngpattern="/^\d+$/">Name
<br/>

The regular expressions must follow the JavaScript regular expression syntax. This
example defines a regular expression that matches strings of digits containing at least 1
digit.

ng-required
The ngrequired directive checks if the value of the form field is empty or not. Actually,
you just use the requiredattribute of HTML5, and AngularJS detects it automatically.

Checking Field Validation State


If you give the <form> element a name attribute, then the form will be add to
the $scope object as a property. Here is an example:
<formname="myFormNg"ngsubmit="myForm.submitTheForm()">
...

112

</form>

When you call a function on the $scope object (a function added to the $scope object by
your controller function), you can access the ngFormController object via its name, like
this:
$scope.myFormNg

If you add a name attribute to the form fields inside the form,
their ngModelController objects will be accessible as properties on
the ngFormController object. Here is an example:
<formname="myFormNg"ngsubmit="myForm.submitTheForm()">
<inputname="firstName"type="text"ngmodel="myForm.firstName">
</form>

You can now access the ngModelController of the firstName input field like this:
$scope.myFormNg.firstName

Both ngFormController and ngModelController objects contain a set of properties that


tell if the form or input field is valid. The properties are:

Property

Description

$pristine

True if the form has not been changed (no form fields has changed),
false if some fields have been changed.

$dirty

The reverse of $pristine - false if the form has not been changed 113

true if it has.

$valid

True if the form field (or the whole form = all form fields) is valid. False
if not.

$invalid

The reverse of the $valid - false if the field (or all fields in the form) is
valid, true if the field (or a single field in the for) is invalid.

You can use these properties to set a matching CSS class on the input fields. Here is an
example :
<style>
.fieldValid{
border:1pxsolid#00ff00;
}
.fieldInvalid{
border:1pxsolid#ff0000;
}
</style>

<divngcontroller="MyController">
<formname="myFormNg">
<inputtype="text"ngclass="myForm.getFormFieldCssClass(myFormNg.name)"

114

id="name"name="name"ngmodel="myForm.name"ngminlength="2">Name
<br/>
</form>
</div>

<script>
angular.module("myapp",[])
.controller("MyController",function($scope,$http){
$scope.myForm={};

$scope.myForm.getFormFieldCssClass=function(ngModelController){
//console.log("gettingcssclass:"+ngModelController.
$valid);
if(ngModelController.$pristine)return"";
returnngModelController.$valid?"fieldValid":
"fieldInvalid";
}
});
</script>

Notice the ngclass directive on the input field. This directive calls
the myForm.getFormFieldCssClass()function using myFormNg.name as parameter. This is
the ngModelController for the name input element.
ThemyForm.getFormFieldCssClass() just returns the matching CSS class as a string.
You can also use the validation properties to show or hide div elements with validation
messages. Here is the form from before, with a div added:
115

<divngcontroller="MyController">
<formname="myFormNg"ngsubmit="myForm.submitTheForm()"novalidate>

<inputtype="text"ngclass="myForm.getFormFieldCssClass(myFormNg.name)"
id="name"name="name"ngmodel="myForm.name"ngminlength="2">Name
<br/>

<divngshow="myFormNg.name.$invalid">
Youmustenteravalidname.
</div>

</form>
</div>

Notice the ngshow directive on the div element. This directive uses the value of
the myFormNg.name.$invalidvalidation property to determine if the div should be shown
or not.
Remember that you can access the $pristine, $dirty, $valid and $invalid properties
of thengFormController too. These properties contain the validation state of the whole
form. This button code example disables the submit button if the form is invalid:
<buttonngdisabled="myFormNg.$invalid">SubmitForm</button>

Submitting Forms
You can submit a form in two ways:

Using a button element with an ngclick attribute.


Using an ngsubmit attribute (directive) on the form element.
116

In both cases a JavaScript function is called on the $scope object. You attach this
JavaScript function to the $scopeobject in your controller function. The JavaScript
function should send the data from the form to your server via AJAX.
Here is a form that uses the ngclick attribute on a button element:
<divngcontroller="MyController">
<form>
<inputtype="text"id="name"ngmodel="myForm.name"ngminlength="5"ng
maxlength="12">Name<br/>

<selectngmodel="myForm.car">
<optionvalue="nissan">Nissan</option>
<optionvalue="toyota">Toyota</option>
<optionvalue="fiat">Fiat</option>
</select>

<buttonngclick="myForm.submitTheForm()">SubmitForm</button>
</form>

<div>
{{myForm.name}}
</div>
<div>
{{myForm.car}}
</div>
</div>

117

<script>
angular.module("myapp",[])
.controller("MyController",function($scope,$http){
$scope.myForm={};
$scope.myForm.name="JakobJenkov";
$scope.myForm.car="nissan";

$scope.myForm.submitTheForm=function(item,event){
console.log(">Submittingform");
vardataObject={
name:$scope.myForm.name
,car:$scope.myForm.car
};

varresponsePromise=$http.post("/angularjsexamples/jsontestdata.jsp",
dataObject,{});
responsePromise.success(function(dataFromServer,status,headers,config){
console.log(dataFromServer.title);
});
responsePromise.error(function(data,status,headers,config){
alert("Submittingformfailed!");
});
}

118

});
</script>

Notice how the ngclick attribute points to the myForm.submitTheForm() function, and
notice how thesubmitTheForm() function is attached to the $scope object inside the
controller function.
Here is the same form using an ngsubmit attribute to submit the form:
<formngsubmit="myForm.submitTheForm()">
<inputtype="text"id="name"ngmodel="myForm.name"ngminlength="5"ng
maxlength="12">Name<br/>

<selectngmodel="myForm.car">
<optionvalue="nissan">Nissan</option>
<optionvalue="toyota">Toyota</option>
<optionvalue="fiat">Fiat</option>
</select>

<inputtype="submit"value="SubmitForm">

</form>

As you can see, the two mechanisms are very similar. They both call a submit function
on the $scope object.

119

Next: AngularJS $timeout and $interval

$timeout
o Injecting $timeout
o

Scheduling a Function Call

$interval
o

Injecting $interval

Scheduling a Repeated Function Call

Executing $digest() After the Scheduled Function Call

AngularJS has two timer services, $timeout and $interval, which you can use to call
functions in your application. The $timeout and $interval services are similar in their
functionality to JavaScript's setTimeout() andsetInterval() functions (actually
belonging to the window object). The functionality of these services is also similar, so I
will cover both in this text.

$timeout
The $timeout service can be used to call another JavaScript function after a given time
delay. The $timeout service only schedules a single call to the function. For repeated
calling of a function, see $interval later in this text.

Injecting $timeout
To use the $timeout service you must first get it injected into a controller function. Here
is an example that injects the$timeout service into a controller function:
varmyapp=angular.module("myapp",[]);

myapp.controller("MyController",function($scope,$timeout){

120

});

Notice the $timeout parameter of the controller function. Into this parameter
the $timeout service will be injected by AngularJS, just like any other AngularJS service
you would want to use in your controller function.

Scheduling a Function Call


Once the $timeout service is injected into your controller function, you can use it to
schedule function calls. Here is an example that used the $timeout service to schedule
a function call 3 seconds later:
varmyapp=angular.module("myapp",[]);

myapp.controller("MyController",function($scope,$timeout){

$timeout(callAtTimeout,3000);

});

functioncallAtTimeout(){
console.log("Timeoutoccurred");
}

This example schedules a function call to callAtTimeout() after 3 seconds (3000


milliseconds).
If you want to call a function on the $scope object, you can do so like this:
varmyapp=angular.module("myapp",[]);

121

myapp.controller("DIController",function($scope,$timeout){

$scope.callAtTimeout=function(){
console.log("$scope.callAtTimeoutTimeoutoccurred");
}

$timeout(function(){$scope.callAtTimeout();},3000);
});

Notice the function passed to the $timeout service. This function calls
the callAtTimeout() function on the$scope object.

$interval
The $interval service is similar in function to the $timeout service, except it schedules
a function for repeated execution with a time interval in between.

Injecting $interval
To use the $interval service you must have it injected into a controller function. Here is
an example that injects the$interval service into a controller function:
varmyapp=angular.module("myapp",[]);

myapp.controller("MyController",function($scope,$interval){

});

122

As you can see, it is very similar to how you inject any other service in AngularJS.

Scheduling a Repeated Function Call


Once the $interval service is injected into your controller function, you can use it to
schedule repeated function calls. Here is an example that used the $interval service to
schedule a function call every 5 seconds:
varmyapp=angular.module("myapp",[]);

myapp.controller("MyController",function($scope,$interval){

$interval(callAtInterval,5000);

});

functioncallAtInterval(){
console.log("Intervaloccurred");
}

This example schedules a function call to callAtInterval() every 5 seconds (5000


milliseconds).
If you want to call a function on the $scope object instead, you can do so like this:
varmyapp=angular.module("myapp",[]);

myapp.controller("DIController",function($scope,$interval){

123

$scope.callAtInterval=function(){
console.log("$scope.callAtIntervalIntervaloccurred");
}

$interval(function(){$scope.callAtInterval();},3000);
});

The function passed to the $interval service calls the callAtInterval() function on
the $scope object.

Executing $digest() After the Scheduled Function Call


If the function you schedule for execution makes changes to variables in
the $scope object, or make changes to any other variable which your application is
watching, your application needs to execute $scope.$digest() after the scheduled
function call finishes. Why that is necessary is explained in my tutorial about $watch(),
$digest() and $apply().
By default AngularJS already calls $digest() after the scheduled function call finishes,
so you don't have to do that explicitly. You can, however, specify if AngularJS
should not call $digest() after the scheduled function call. If, for instance, your
scheduled function call only updates an animation but does not change
any $scope variables, then it is a waste of CPU time to call $digest() after the function
finishes.
Both $timeout and $interval have a third, optional parameter which can specify if
the $digest() method is to be executed after the scheduled function finishes. Actually,
the third parameter specifies if the call to the scheduled function should be done inside
an $apply() call. Here is an example of how to use this third parameter:
$interval(function(){$scope.callAtInterval();},3000,true);

124

$interval(function(){$scope.callAtInterval();},3000,false);

These two $interval examples both have a third parameter passed to


the $interval service. This parameter can be either true or false. A value
of true means that the scheduled function should be called inside an $apply()call. A
value of false means that it should not be called inside an $apply() call
(meaning $digest() will not get called after the scheduled function finishes).

Next: AngularJS Custom Directives


Table of Contents

Custom Directive Introduction


Directive Types

A Basic Directive

Isolating the $scope From the Directive

The compile() and link() Functions


o

Setting Only a link() Function

Directives Which Wraps Elements Via Transclusion

Custom Directive Introduction


AngularJS directives are what controls the rendering of the HTML inside an AngularJS
application. Examples of directives are the interpolation directive ({{}}), the ng
repeat directive and ngif directive.
It is possible to implement your own directives too. This is what AngularJS refers to as
"teaching HTML new tricks". This text will show you how to do that.

Directive Types
You can implement the following types of directives:
125

Element directives
Attribute directives

CSS class directives

Comment directives

Of these, AngularJS recommends that you try to use element and attribute directives,
and leave the CSS class and comment directives (unless absolutely necessary).
The type of a directive determines how the directive is activated. An element directive is
activated when AngularJS finds a matching HTML element in the HTML template. An
attribute directive is activated when AngularJS finds a matching HTML element attribute.
A CSS class directive is activated when AngularJS finds a matching CSS Class. And, a
comment directive is activated when AngularJS finds a matching HTML comment.

A Basic Directive
You register a directive with a module. Here is an example of how that looks:
myapp=angular.module("myapp",[]);

myapp.directive('div',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/

directive.template="Myfirstdirective:{{textToInsert}}";

returndirective;
});

126

Notice the call to the directive() function on the module. When you call this function
you can register a new directive. The first parameter to the directive() function call is
the name of the directive to register. This name is what you use in your HTML templates
when you want to activate the directive. In this example I have used the name ' div'
which means that the directive is activated every time an HTML element named div is
found in the HTML template.
The second parameter passed to the directive function is a factory function. This
function should return a directive definition when invoked. AngularJS will invoke this
function to obtain a JavaScript object which contains the definition of the directive. If you
look inside the function in the above example you will see that it does indeed return a
JavaScript object.
The JavaScript object returned from the factory function has two properties:
A restrict field and a template field.
The restrict field is used to set if the directive should be activated by a matching
HTML element, or an element attribute. By setting restrict to E you specify that only
HTML elements named div should activate the directive. By setting restrict to A you
specify that only HTML attributes named div should activate the directive. You can also
use a value of AE which will match both HTML element names and attribute names.
The template field is an HTML template that will replace the content of the
matched div element. It will work as if the content of the matched div element had not
been there, and instead this HTML template had been located in the same place.
Imagine that your HTML page has this HTML:
<divngcontroller="MyController">
<div>Thisdivwillbereplaced</div>
</div>

Then the added directive would be activated when AngularJS finds the
inner div element. Instead of this div element, this HTML will be inserted:
Myfirstdirective:{{textToInsert}}

127

As you can see, this HTML contains an interpolation directive ( {{textToInsert}}).


AngularJS will interpret this HTML again, so that the interpolation directive actually
works. The value of the $scope.textToInsert property will be inserted at this point in
the HTML.

The template and templateUrl Properties


The easiest way to create your own directives is as shown in the example above. Your
directive is intended to generate HTML, and you put that HTML inside
the template attribute of the directive definition object. Here is the directive definition
repeated from earlier, with the template string marked in bold:
myapp=angular.module("myapp",[]);

myapp.directive('div',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/
directive.template="Myfirstdirective:{{textToInsert}}";

returndirective;
});

In case that HTML template grows big, it is gets hard to write and maintain the HTML
inside a JavaScript string. You can then put the HTML into its own file and have
AngularJS load it from that file. You do so by putting the URL of the HTML template file
into the templateUrl property of the directive definition object. Here is an example:
myapp=angular.module("myapp",[]);

128

myapp.directive('div',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/
directive.templateUrl="/myapp/htmltemplates/divtemplate.html";

returndirective;
});

AngularJS will now load the HTML template from the URL set in
the templateUrl property.
Using the separate HTML template file and the templateUrl property is especially useful
when you create more specialized directives, like a directives showing user info. Here is
an example:
myapp=angular.module("myapp",[]);

myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/
directive.templateUrl="/myapp/htmltemplates/userinfotemplate.html";

returndirective;
});

129

This example creates a directive that is activated whenever AngularJS finds


a <userinfo> element. AngularJS loads the HTML template found at /myapp/html
templates/userinfotemplate.html, and interprets that as if it had been located inside
the parent HTML file from the beginning.

Isolating the $scope From the Directive


In the example above the userinfo directive was bound hard to the $scope variable
because the HTML template referenced the textToInsert property directly.
Referencing $scope variables directly makes it hard to reuse the directive more than
once within the same controller, since the $scope variables typically have the same
values everywhere inside the same controller. For instance, if you wanted to have this
HTML in your page:
<userinfo></userinfo>
<userinfo></userinfo>

Then the two <userinfo> elements would be replaced by the same HTML template,
which is bound to the same$scope variable. The result would be that the
two <userinfo> elements would be replaced by the exact same HTML code.
To be able to bind the two <userinfo> elements to different values in the $scope object,
you need to bind the HTML template to an isolate scope.
An isolate scope is a separate scope object tied to the directive. Here is how you define
it in the directive definition object:
myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';

directive.template="User:{{user.firstName}}{{user.lastName}}";

130

directive.scope={
user:"=user"
}

returndirective;
})

Notice how the HTML template has two interpolation directives bound
to {{user.firstName}} and{{user.lastName}}. Notice the user. part. And notice
the directive.scope property. The directive.scopeproperty is a JavaScript object
which contains a property named user. The directive.scope property is the isolate
scope object, and the HTML template is now bound to the directive.scope.user object
(via the{{user.firstName}} and {{user.lastName}} interpolation directives).
The directive.scope.user property is set to "=user". That means, that
the directive.scope.user property is bound to the property in the scope property (not
in the isolate scope) with the name passed to the user attribute of
the <userinfo> element. It sounds confusing, so look at this HTML example:
<userinfouser="jakob"></userinfo>
<userinfouser="john"></userinfo>

These two <userinfo> element contain a user attribute. The value of these attributes
contain the names of properties in the $scope object which are to be referenced by the
isolate scope object's userinfo property.
Here is a full example:
<userinfouser="jakob"></userinfo>
<userinfouser="john"></userinfo>

131

<script>
myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';

directive.template="User:<b>{{user.firstName}}</b>
<b>{{user.lastName}}</b>";

directive.scope={
user:"=user"
}

returndirective;
});

myapp.controller("MyController",function($scope,$http){
$scope.jakob={};
$scope.jakob.firstName="Jakob";
$scope.jakob.lastName="Jenkov";

$scope.john={};
$scope.john.firstName="John";

132

$scope.john.lastName="Doe";
});

</script>

The compile() and link() Functions


If you need to do something more advanced inside your directive, something that you
cannot do with an HTML template, you can use the compile() and link() functions
instead.
The compile() and link() functions define how the directive is to modify the HTML that
matched the directive.
The compile() function is called once for each occurrence of the directive in the HTML
page. The compile()function can then do any one-time configuration needed of the
element containing the directive.
The compile() function finishes by returning the link() function. The link() function is
called every time the element is to be bound to data in the $scope object.
As mentioned, you add the compile() function to the directive definition object, and
the compile() function has to return the link() function when executed. Here is how
that looks:
<script>
myapp=angular.module("myapp",[]);
myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/

133

directive.compile=function(element,attributes){
//doonetimeconfigurationofelement.

varlinkFunction=function($scope,element,atttributes){
//bindelementtodatain$scope
}

returnlinkFunction;
}

returndirective;
});
</script>

The compile() function takes two parameters: The element and attributes parameters.
The element parameter is a jqLite wrapped DOM element. AngularJS contains a lite
version of jQuery to help you do DOM manipulation, so the element's DOM manipulation
methods are the same as you know from jQuery.
The attributes parameter is a JavaScript object containing properties for all the
attributes of the DOM element. Thus, to access an attribute named type you would
write attributes.type.
The link() function takes three parameters: The $scope parameter,
the element parameter and the attributesparameter.
The element and attributes parameter is the same as passed to
134

the compile() function. The$scope parameter is the normal scope object, or an isolate
scope in case you have specified one in the directive definition object.
The compile() and link() function names are actually confusing. They are inspired by
compiler terms. I can see the resemblance, but a compiler parses an input once, and
creates an output. A directive configures an HTML element and then updates that HTML
subsequently whenever the $scope object changes.
A better name for the compile() function would have been something
like create(), init() or configure(). Something that signals that this function is only
called once.
A better name for the link() function would have been something
like bind() or render(), which signals that this function is called whenever the directive
needs to bind data to it, or to re-render it.
Here is a full example that shows a directive that uses both
a compile() and link() function:
<divngcontroller="MyController">
<userinfo>Thiswillbereplaced</userinfo>
</div>

<script>
myapp=angular.module("myapp",[]);
myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/

directive.compile=function(element,attributes){

135

element.css("border","1pxsolid#cccccc");

varlinkFunction=function($scope,element,attributes){
element.html("Thisisthenewcontent:"+$scope.firstName);
element.css("backgroundcolor","#ffff00");
}

returnlinkFunction;
}

returndirective;
})
myapp.controller("MyController",function($scope,$http){
$scope.cssClass="notificationDiv";

$scope.firstName="Jakob";

$scope.doClick=function(){
console.log("doClick()called");
}
});
</script>

The compile() function sets a border on the HTML element. This is only executed once
because the compile()function is only executed once.
136

The link() function replaces the content of the HTML element, and sets the
background color to yellow.
There is no particular reason why the border was set in the compile() function, and the
background color in thelink() function. Both could have been set in
the compile() function, or both in the link() function. If set in thecompile() function
they would only have been set once (which is often what you want). If set in
the link() function they would be set every time the HTML element is bound to data in
the $scope object. This might be useful if you needed to set the border and background
color differently depending on data in the $scope object.

Setting Only a link() Function


Sometimes you do not need the compile() step for your directive. You only need
th link() function. In that case you can set the link() function directly on the directive
definition object. Here is the example from before, with only a link function:
<divngcontroller="MyController">
<userinfo>Thiswillbereplaced</userinfo>
</div>

<script>
myapp=angular.module("myapp",[]);
myapp.directive('userinfo',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/

directive.link=function($scope,element,attributes){
element.html("Thisisthenewcontent:"+$scope.firstName);

137

element.css("backgroundcolor","#ffff00");
}

returndirective;
})
myapp.controller("MyController",function($scope,$http){
$scope.cssClass="notificationDiv";

$scope.firstName="Jakob";

$scope.doClick=function(){
console.log("doClick()called");
}
});
</script>

Notice how the link() function does the same as the link() function returned in the
previous example.

Directives Which Wraps Elements Via Transclusion


The examples we have seen so far all set the content of the element matching the
directive themselves, either via JavaScript code or an HTML template. But what if you
wanted a directive to wrap elements inserted into the directive body by the developer?
For instance:
<mytransclude>Thisisatranscludeddirective{{firstName}}</mytransclude>

138

The directive is marked by the <mytransclude> element. But the content inside it is set
by the developer. Thus, this part of the HTML should not be replaced by the directive's
HTML template. We actually want that part of the HTML to be processed by AngularJS.
This processing is called "transclusion".
In order to make AngularJS process the HTML inside a directive, you have to set
the transclude property of the directive definition object to true. You will also have to
tell AngularJS what part of the directive's HTML template that is to contain the
transcluded HTML. You do so by inserting the ngtransclude attribute (a directive,
really) into the HTML element in the HTML template where you want the transcluded
HTML inserted.
Here is an AngularJS directive that shows how to use transclusion:
<mytransclude>Thisisatranscludeddirective{{firstName}}</mytransclude>

<script>
myapp=angular.module("myapp",[]);
myapp.directive('mytransclude',function(){
vardirective={};

directive.restrict='E';/*restrictthisdirectivetoelements*/
directive.transclude=true;
directive.template="<divclass='myTransclude'ngtransclude></div>";

returndirective;
});
myapp.controller("MyController",function($scope,$http){
$scope.firstName="Jakob";

139

});
</script>

Notice the HTML inside the <mytransclude> element. This HTML code contains the
interpolation directive{{firstName}}. We want AngularJS to process this HTML for us
so that interpolation directive is executed. To achieve that I have set
the transclude property to true on the directive definition object. I have also inserted
an ngtransclude attribute into the HTML template. This attribute tells AngularJS what
element to insert the transcluded HTML into.

Next: AngularJS Modularization & Dependency Injection


Table of Contents

Value
o

Factory
o

Injecting Values Into a Factory

Service
o

Injecting a Value

Injecting Values Into a Service

Providers
o

Configuring a Provider

Constants

Dependencies Between Modules

Minification Safe Dependency Injection in AngularJS

AngularJS comes with a built-in dependency injection mechanism. You can divide your
application into multiple different types of components which AngularJS can inject into
each other. Modularizing your application makes it easier to reuse, configure and test
the components in your application.
140

AngularJS contains the following core types of objects and components:

Value
Factory

Service

Provider

Constant

These core types can be injected into each other using AngularJS dependency injection
mechanism. Throughout the rest of this text I will explain how to define and inject these
components into each other.

Value
A value in AngularJS is a simple object. It can be a number, string or JavaScript object.
Values are typically used as configuration which is injected into factories, services or
controllers.
A value has to belong to an AngularJS module. Here are three examples that add
values to an AngularJS module:
varmyModule=angular.module("myModule",[]);

myModule.value("numberValue",999);

myModule.value("stringValue","abc");

myModule.value("objectValue",{val1:123,val2:"abc"});

The values are defined using the value() function on the module. The first parameter is
the name of the value, and the second parameter is the value itself. Factories, services
and controllers can now reference these values by their name.
141

Injecting a Value
Injecting a value into an AngularJS controller function is done simply by adding a
parameter with the same name as the value (the first parameter passed to
the value() function when the value is defined). Here is an example:
varmyModule=angular.module("myModule",[]);

myModule.value("numberValue",999);

myModule.controller("MyController",function($scope,numberValue){

console.log(numberValue);

});

Notice how the second parameter of the controller function has the same name as the
value.

Factory
Factory is a function that creates values. When a service, controller etc. needs a value
injected from a factory, the factory creates the value on demand. Once created, the
value is reused for all services, controllers etc. which need it injected. Thus, a factory
differs from a value in that it can use a factory function to create the object it returns.
You can also inject values into a factory for use when creating the object. You cannot do
that with a value.
Here is an example that defines a factory on a module, and a controller which gets the
factory created value injected:

142

varmyModule=angular.module("myModule",[]);

myModule.factory("myFactory",function(){
return"avalue";
});

myModule.controller("MyController",function($scope,myFactory){

console.log(myFactory);

});

As you can see, it is very similar to defining and injecting a value object. Keep in mind
that it is not the factory function that is injected, but the value produced by the factory
function.

Injecting Values Into a Factory


You can inject a value into a factory. It works just like when a value is injected into a
controller. Here is an example:
varmyModule=angular.module("myModule",[]);

myModule.value("numberValue",999);

myModule.factory("myFactory",function(numberValue){

143

return"avalue:"+numberValue;
});

In this example the injected value is used to create the object created by the factory
function.

Service
A service in AngularJS is a singleton JavaScript object which contains a set of functions.
The functions contain whatever logic is necessary for the service to carry out its work.
AngularJS services are created using the service() function on a module. Here is an
example:
functionMyService(){
this.doIt=function(){
console.log("done");
}
}

varmyModule=angular.module("myModule",[]);

myModule.service("myService",MyService);

As you can see, services are defined somewhat differently than factories and values.
First of all, the service is defined as a separate, named function. That is because
services in AngularJS are created using the new keyword. Thus, AngularJS will do this
internally:

144

vartheService=newMyService();

Apart from defining services as functions with functions inside, you add them to and use
them with AngularJS just like you would with a value or function. You inject a service
into a controller like this:
functionMyService(){
this.doIt=function(){
console.log("done");
}
}

varmyModule=angular.module("myModule",[]);

myModule.service("myService",MyService);

myModule.controller("MyController",function($scope,myService){

myService.doIt();

});

145

Injecting Values Into a Service


You can inject values into a service, just like you can inject values into controllers, or
services into controllers etc. Here is an example:
varmyModule=angular.module("myModule",[]);

myModule.value("myValue","12345");

functionMyService(myValue){
this.doIt=function(){
console.log("done:"+myValue;
}
}

myModule.service("myService",MyService);

Notice how the parameter to the MyService function is named the same as the value
registered on the module. Thus, the value will be injected into the service when it is
created.

Providers
Providers in AngularJS is the most flexible form of factory you can create. You register a
provider with a module just like you do with a service or factory, except you use
the provider() function instead. Here is an AngularJS provider example:
varmyModule=angular.module("myModule",[]);

146

myModule.provider("mySecondService",function(){
varprovider={};

provider.$get=function(){
varservice={};

service.doService=function(){
console.log("mySecondService:ServiceDone!");
}

returnservice;
}

returnprovider;
});

As you can see, the provider() function takes 2 parameters. The first parameter is the
name of the service / object which the provider creates. In this case the name
is mySecondService. The second parameter is the function which creates the provider.
Note: The provider is itself a factory, so at this time no actual service or object is created
from the provider. Only the function creating the provider is defined.
When you look at the function creating the provider you can see that the provider is a
JavaScript object.
The JavaScript provider object contains a single $get() function. This is the factory
function of the provider. In other words, the $get() function creates whatever the
provider creates (service, value etc.). In the example above, the provider creates a

147

service object which contains a single service function (standard JavaScript function)
calleddoService().
In order to get the product of a provider injected into a controller, do specify a
dependency on the provider, just like you would with a service. What is injected into the
controller is the product created by the provider, not the provider itself. Here is an
AngularJS provider injection example:
myModule.controller("MyController",function($scope,mySecondService){

$scope.whenButtonClicked=function(){
mySecondService.doIt();
}

});

As you can see, the name of the provider is used as a parameter in the controller
function. The object created by the provider's $get() function will be injected into this
parameter.

Configuring a Provider
It is possible to configure a provider further via calls to its function during the
configuration phase of a module. Here is an example:
varmyModule=angular.module("myModule",[]);

myModule.provider("mySecondService",function(){
varprovider={};
varconfig={configParam:"default"};

148

provider.doConfig=function(configParam){
config.configParam=configParam;
}

provider.$get=function(){
varservice={};

service.doService=function(){
console.log("mySecondService:"+config.configParam);
}

returnservice;
}

returnprovider;
});

myModule.config(function(mySecondServiceProvider){
mySecondServiceProvider.doConfig("newconfigparam");
});

myModule.controller("MyController",function($scope,mySecondService){

149

$scope.whenButtonClicked=function(){
mySecondService.doIt();
}

});

Notice how the provider object now has an extra function called doConfig(). This
function can be used to set a configuration parameter on the provider.
Notice also the call to the myModule.config() function. The config function takes a
function as parameter. This function can configure the module. The function passed
to config() takes a single parameter namedmySecondServiceProvider. That is the
same name the provider is registered with plus Provider as suffix. The suffix tells
AngularJS to inject the provider itself, and not the object created by the provider. Inside
the function passed to the config() function
the mySecondServiceProvider.doConfig() function is called, which sets the config
parameter on the provider.
The controller defined later in the example just depends on the object created by the
provider (not the provider itself). It does so by taking a parameter
named mySecondService which is the name the provider of the service is registered with.
As you can see, the service used from inside the $scope.whenButtonClicked() function.

Constants
In the previous section on providers you saw how to configure a provider via
the module.config() function. Unfortunately you cannot inject values into
the module.config() function. Instead you can inject constants.
Constants in AngularJS are defined using the module.constants() function. Here is an
AngularJS constant example:

150

myModule.constant("configValue","constantconfigvalue");

This constant can now be injected into the module.config() function like this:
myservices.config(function(mySecondServiceProvider,configValue){
mySecondServiceProvider.doConfig(configValue);
});

As you can see, the parameter configValue matches the name of the constant which is
also configValue. Thus the value of the constant will be injected into this parameter.
The constant value is then passed as parameter to the doConfig() function on
the mySecondServiceProvider provider.

Dependencies Between Modules


As you have seen, values, factories and services are added to an AngularJS module. It
is possible for one module to use the values, factories and services of another module.
In order to do so, a module needs to declare a dependency on the module which
contains the values, factories and services it wants to use. Here is an example:
varmyUtilModule=angular.module("myUtilModule",[]);

myUtilModule.value("myValue","12345");

varmyOtherModule=angular.module("myOtherModule",['myUtilModule']);

myOtherModule.controller("MyController",function($scope,myValue){

151

Notice how the second module (myOtherModule) lists the name of the first module
(myUtilModule) in the second parameter (inside the array) passed to
the angular.module() function. This tells AngularJS that all values, factories and
services defined inside the myUtilModule should be available inside
the myOtherModule module too. In other words, myOtherModule depends
on myUtilModule.
Second, notice how the MyController controller function now declares a parameter
named myValue. This value will be provided from the value registered on
the myUtilModule module.

Minification Safe Dependency Injection in AngularJS


When you minify JavaScript the JavaScript minifier replaces the names of local
variables and parameters with shorter names. However, AngularJS uses the parameter
names of controller functions, factories, services and providers to decide what to inject
into their factory functions. If the names are changed, AngularJS cannot inject the
correct objects.
To make your AngularJS code minification safe, you need to provide the names of the
objects to inject as strings. You wrap these strings in an array together with the function
that needs the values injected. Here is an AngularJS minification safe dependency
injection example:
varmyapp=angular.module("myapp",['myservices']);

myapp.controller("AController",['$scope',function(p1){
p1.myvar="thevalue";
}]);

This example injects the $scope object into the p1 parameter of the controller function.
152

Notice how the controller function is registered. Instead of passing the controller function
to theangular.controller function directly, an array is passed instead. This array
contains the name of the value to inject into the controller function, as well as the
controller function itself. The controller function is always the last value in this array. If
you need to inject more than one value, the value names are listed in the beginning of
the array and in the sequence they are to be injected into the function. Here is a
minification safe multi value example:
varmyapp=angular.module("myapp",['myservices']);

myapp.controller("AController",['$scope','$http',function(p1,p2){
p1.myvar="thevalue";
p2.get("/myservice.json");
}]);

This example injects the $scope object into the p1 parameter, and the $http service into
the p2 parameter of the controller function.
Now it no longer matters what the parameter names of the controller function are.
AngularJS will use the strings in the beginning of the array to determine what to inject
into the controller function.
The same mechanism can be used for factories, services and providers to provide
minification safe dependency injection. Here is a minification safe factory, service and
provider example:
varmyutil=angular.module("myutil",[]);

myutil.value("safeValue","asafevalue");

153

myutil.factory("safeFactory",['safeValue',function(p1){
return{value:p1};
}]);

functionMySafeService(p1){
this.doIt=function(){
return"MySafeService.doIt()called:"+p1.value;
}
}
myutil.service("safeService",['safeFactory',MySafeService]);

myutil.provider("safeService2",function(){
varprovider={};

provider.$get=['safeService',function(p1){
varservice={};

service.doService=function(){
console.log("safeServicefromprovider:"+p1.doIt());
}

154

returnservice;
}];

returnprovider;
});

myapp.controller("AController",['$scope','safeService2',function(p1,p2){
p1.myvar="thevalue";
p2.doService();
}]);

Notice especially the declaration of the provider. Notice how the dependencies are not
specified on the provider factory function, but on the $get() function of the provider
returned from inside the provider factory function. Actually, an array with names of
dependencies and the function implementation is used instead of just a $get() function.
Other than that, specifying dependencies works the same for providers as for factories,
services and controller functions.

Next: AngularJS Routes


Table of Contents

Including the AngularJS Route Module


Declaring a Dependency on the AngularJS Route Module

The ngView Directive

Configuring the $routeProvider

Links to Routes

Route Parameters
155

AngularJS routes enable you to create different URLs for different content in your
application. Having different URLs for different content enables the user to bookmark
URLs to specific content, and send those URLs to friends etc. In AngularJS each such
bookmarkable URL is called a route.
AngularJS routes enables you to show different content depending on what route is
chosen. A route is specified in the URL after the # sign. Thus, the following URL's all
point to the same AngularJS application, but each point to different routes:
http://myangularjsapp.com/index.html#books
http://myangularjsapp.com/index.html#albums
http://myangularjsapp.com/index.html#games
http://myangularjsapp.com/index.html#apps

When the browser loads these links, the same AngularJS application will be loaded
(located athttp://myangularjsapp.com/index.html), but AngularJS will look at the route
(the part of the URL after the #) and decide what HTML template to show.
At this point it may sound a little abstract, so let us look at a fully working AngularJS
route example:
<!DOCTYPEhtml>
<htmllang="en">
<head>
<title>AngularJSRoutesexample</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular
route.min.js"></script>
</head>

156

<bodyngapp="sampleApp">

<ahref="#/route1">Route1</a><br/>
<ahref="#/route2">Route2</a><br/>

<divngview></div>

<script>
varmodule=angular.module("sampleApp",['ngRoute']);

module.config(['$routeProvider',
function($routeProvider){
$routeProvider.
when('/route1',{
templateUrl:'angularroutetemplate1.jsp',
controller:'RouteController'
}).
when('/route2',{
templateUrl:'angularroutetemplate2.jsp',
controller:'RouteController'
}).
otherwise({
redirectTo:'/'

157

});
}]);

module.controller("RouteController",function($scope){

})
</script>

Each part of this sample application will be explained in the following sections.

Including the AngularJS Route Module


The first thing to notice in the example application above is the extra JavaScript included
inside the head section:
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular
route.min.js"></script>

The AngularJS Route module is contained in its own JavaScript file. To use it we must
include in our AngularJS application.

Declaring a Dependency on the AngularJS Route Module


The second thing to notice is that the applications's AngularJS module
(called sampleApp) declares a dependency on the AngularJS route module:
varmodule=angular.module("sampleApp",['ngRoute']);

The application's module needs to declare this dependency in order to use


the ngRoute module. This is explained in more detail in my modularization and
dependency injection tutorial, in the section about dependencies-between-modules.
158

The ngView Directive


The third thing to notice in the example above is the use of the ngView directive:
<divngview></div>

Inside the div with the ngView directive (can also be written ngview) the HTML template
specific to the given route will be displayed.

Configuring the $routeProvider


The fourth thing to notice in the example shown at the beginning of this text is the
configuration of the$routeProvider. The $routeProvider is what creates
the $route service. By configuring the $routeProviderbefore the $route service is
created we can set what routes should result in what HTML templates being displayed.
Here is the code from the example:
<script>
module.config(['$routeProvider',
function($routeProvider){
$routeProvider.
when('/route1',{
templateUrl:'angularroutetemplate1.jsp',
controller:'RouteController'
}).
when('/route2',{
templateUrl:'angularroutetemplate2.jsp',
controller:'RouteController'
}).

159

otherwise({
redirectTo:'/'
});
}]);
</script>

The $routeProvider is configured in the module's config() function. We pass a


configuration function to the module's config() function which takes
the $routeProvider as parameter. Inside this function we can now configure
the $routeProvider.
The $routeProvider is configured via calls to the when() and otherwise() functions.
The when() function takes a route path and a JavaScript object as parameters.
The route path is matched against the part of the URL after the # when the application
is loaded. As you can see, the two route paths passed to the two when() function calls
match the two route paths in the href attribute of the links in the same example.
The JavaScript object contains two properties named templateUrl and controller.
The templateUrl property tells which HTML template AngularJS should load and
display inside the div with the ngView directive. Thecontroller property tells which of
your controller functions that should be used with the HTML template.
The otherwise() function takes a JavaScript object. This JavaScript object tells
AngularJS what it should do if no route paths matches the given URL. In the example
above the browser is redirected to the same URL with #/ as route path.

Links to Routes
The final thing to notice in this example is the two links in the HTML page:
<ahref="#/route1">Route1</a><br/>
<ahref="#/route2">Route2</a><br/>

160

Notice how the part of the URLs after the # matches the routes configured on
the $routeProvider.
When one of these links is clicked, the URL in the browser window changes, and
the div with the ngView directive will show the HTML template matching the route path.

Route Parameters
You can embed parameters into the route path. Here is an AngularJS route path
parameter example:
#/books/12345

This is a URL with a route path in. In fact it pretty much consists of just the route path.
The parameter part is the 12345which is the specific id of the book the URL points to.
AngularJS can extract values from the route path if we define parameters in the route
paths when we configure the$routeProvider. Here is the example $routeProvider from
earlier, but with parameters inserted into the route paths:
<script>
module.config(['$routeProvider',
function($routeProvider){
$routeProvider.
when('/route1/:param',{
templateUrl:'angularroutetemplate1.jsp',
controller:'RouteController'
}).
when('/route2/:param',{
templateUrl:'angularroutetemplate2.jsp',
controller:'RouteController'

161

}).
otherwise({
redirectTo:'/'
});
}]);
</script>

Both of the URLs in the when() calls now define a parameter. It is the part starting from
the colon (:param)
AngularJS will now extract from the URL (route path) whatever comes after
the #/route1/ part. Thus, from this URL:
#/route1/12345

The value 12345 will be extracted as parameter.


Your controller functions can get access to route parameters via the
AngularJS $routeParams service like this:
module.controller("RouteController",function($scope,$routeParams){
$scope.param=$routeParams.param;
})

Notice how the controller function takes the $routeParams service as parameter, and
then copies the parameter named param into the $scope.param property. Now your
AngularJS views can get access to it, or you can use it in AJAX calls etc.
Here is a full AngularJS route parameter example:
<!DOCTYPEhtml>

162

<htmllang="en">
<head>
<title>AngularJSRoutesexample</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
<scriptsrc="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular
route.min.js"></script>
</head>

<bodyngapp="sampleApp">

<ahref="#/route1/abcd">Route1+param</a><br/>
<ahref="#/route2/1234">Route2+param</a><br/>

<divngview></div>

<script>
varmodule=angular.module("sampleApp",['ngRoute']);

module.config(['$routeProvider',
function($routeProvider){
$routeProvider.
when('/route1/:param',{
templateUrl:'angularroutetemplate1.jsp',

163

controller:'RouteController'
}).
when('/route2/:param',{
templateUrl:'angularroutetemplate2.jsp',
controller:'RouteController'
}).
otherwise({
redirectTo:'/'
});
}]);

module.controller("RouteController",function($scope,$routeParams){
$scope.param=$routeParams.param;
})
</script>

</body>
</html>

Next: AngularJS Internationalization


164

Table of Contents

Internationalization in Filters
o The Date Filter
o

The Currency Filter

The Number Filter

Setting the Locale

Full AngularJS Internationalization Example

AngularJS has built-in support for internationalization of numbers and dates. In this text I
will take a look at how they work.

Internationalization in Filters
Some of the built-in AngularJS filters supports internationalization. For instance,
the date and currency filters have built-in support for internationalization. Here is how
you would normally use these filters:
{{theDate|date:'fullDate'}}
{{theValue|currency}}
{{theValue|number}}

The date filter will format the variable theDate as a date according to the locale chosen
in the web app. The same is true for the currency and number filter.
Filters are covered in more detail in the section about filtering in my views and directives
tutorial: AngularJS Filtering.

The Date Filter


The date filter accepts the following values specifying how to format the date:

short
medium

fullDate
165

shortDate

mediumDate

longDate

shortTime

mediumTime

Here are a few date filter examples:


{{theDate|date:'shortDate'}}
{{theDate|date:'longDate'}}

The Currency Filter


The currency filter will use the currency symbol associated with the chosen locale when
formatting a number as a currency. If you need to use a different currency symbol, for
instance if the users wants to see a price in a different currency, you can specify the
currency symbol to the currency filter like this:
{{theValue|currency:'$'}}
{{theValue|currency:''}}
{{theValue|currency:''}}

Notice how the last two examples use the HTML entities for pounds and euros.

The Number Filter


The number filter formats numbers according to the chosen locale. For instance, in
English the thousand separator is . and the decimal separator is , whereas in Danish it
is the opposite. Here is a number filter example:
{{theValue|number}}

166

Setting the Locale


To tell AngularJS what locale (language and country) to use when writing localized
output, you need to include the corresponding AngularJS locale file. Here is an example
that includes the Danish locale:
<scriptsrc="https://code.angularjs.org/1.2.5/i18n/angularlocale_da
dk.js"></script>

Include this after including the AngularJS main JavaScript file, and it should work out of
the box. There nothing more that needs to be done than including this file.
To find the correct locale for your country, look at code.angularjs.org, click on the
version of AngularJS you are using, and then click on the i18n directory. In that directory
you see a list of all the available locales. Find the one that matches the country or
contries you want to support, and then download them and include them in your HTML
page (or reference them directly at code.angularjs.org).

Full AngularJS Internationalization Example


Here is a full AngularJS internationalization example:
<!DOCTYPEhtml>
<htmllang="en">
<head>
<title>AngularJSRoutesexample</title>
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></scrip
t>
<scriptsrc="https://code.angularjs.org/1.2.5/i18n/angularlocale_da
dk.js"></script>
</head>

167

<bodyngapp="myapp">

AngularJSI18n

<divngcontroller="mycontroller">
{{theDate|date:"fullDate"}}<br/>
{{theValue|currency}}
</div>

<script>
varmodule=angular.module("myapp",[]);

module.controller("mycontroller",function($scope){

$scope.theDate=newDate();
$scope.theValue=123.45;

});
</script>

</body>

168

</html>

It is this line which includes the language (locale) JavaScript file:


<scriptsrc="https://code.angularjs.org/1.2.5/i18n/angularlocale_da
dk.js"></script>

Next: AngularJS Critique


Table of Contents

AngularJS Directives And The Declarative / Imperative Paradigm Mismatch


o The Declarative / Imperative Paradigm Mismatch
o

Finding the Declarative / Imperative Balance

HTML5 Canvas & WebGL

Designers Are Not Developers

AngularJS Without Directives?

Two-way Data Binding

Critique Summary

An Alternative

Over the years I have looked at Java Swing, SWT, Flex, GWT, jQuery, SmartClient, JSP,
Wicket, Struts, Spring MVC and now AngularJS, in my long search for the "perfect" GUI
toolkit for web apps. I hoped AngularJS would be the end of my search, but right from
the beginning something in AngularJS smelled wrong to me. It took me some time
before I was able to put my finger on just what it is I don't like.
Don't get me wrong. You can make web apps just fine with AngularJS. There are just
some aspects I don't like - choices I don't agree with. These are:
1.
2.

The AngularJS directives are a suboptimal choice for HTML generation.


The 2-way data binding is not always that useful.
169

Each of these aspects are discussed below.

AngularJS Directives And The Declarative / Imperative


Paradigm Mismatch
My main point of critique is against the AngularJS HTML templating style including
AngularJS directives. These are a core part of AngularJS so you cannot really choose
not to use them.
AngularJS uses the popular {{}} HTML templating style also found in frameworks like
Knockout and Handlebars. Here is an example:
<ol>
<lingrepeat="theIteminmyData.getItems()">{{theItem.text}}</li>
</ol>

While this style works just fine for the simple cases, it works less well for more advanced
cases.
In web apps the code has to insert data into the HTML page somehow. You can
generate the whole HTML page using an imperative language, like Java (on the server)
or JavaScript (in the browser). Or, you can try to "teach HTML new tricks" so HTML
becomes able to do some of the things you can do in an imperative language. Or, you
find a middle ground in which the more static parts of the HTML page is defined using
HTML syntax, and the more advanced parts are created using a imperative language.
HTML is a declarative language, so another way to put it is, that either you mix a bit of
the imperative into the declarative, or a bit of the declarative into the imperative. I will get
back to this again later.
In my opinion generating HTML on the client cases works better than generating HTML
on the server in most cases. It results in cleaner HTML generation code, and cleaner
backend code too. This means, that the imperative language should run in the browser.
In AngularJS that language is JavaScript and that is just fine.

170

Using declarative HTML templates with a bit of data binding injected is not a new idea. It
has been tried before in JSP (JavaServer Pages). Here is an example:
<span><%=myObject.getMyProperty()%></span>

In AngularJS it would look like this:


<span>{{myObject.getMyProperty()}}</span>

This data binding injection style is incredibly simple for the simple cases, and thus
immediately appeals to most developers. However, as soon as your web app gets more
advanced you realize that you need some kind of imperative control logic to direct the
HTML generation. Two imperative constructs you will soon need is looping and
branching (if-statements). Here is how looping looks in JSP in the first versions:
<%
for(inti=0;i<list.size();i++){
MyObjectmyObject=(MyObject)list.get(i);
%>
<span><%=myObject.getMyProperty()%></span>
<%}%>

Notice how the <% %> markers switches between Java and HTML. While this allowed
imperative control logic to be mixed with the declarative HTML, developers soon
realized that mixing Java directly into the HTML resulted in really messy code when the
HTML pages got more advanced. The syntaxes of Java and HTML just didn't
complement each other very well.
To solve that problem the JSP standard added a concept called "Tag Libraries". Tag
libraries used an XML syntax to allow imperative control to be mixed with the HTML.
Early frameworks like Struts utilized this to create tag libraries for data binding, iteration,
branches etc. Here is an early iteration example:

171

<logic:iterateid="theBean"name="beans">
<span><bean:writename="theBean"property="theProperty"/></span>
</logic:iterate>

This way the syntax of the imperative control logic complements HTML better. However,
you run into other problems instead. First, it is not so easy to express advanced
constructs like recursive iteration of tree or graph data structures. Second, your HTML
template gets messy when you insert too much imperative logic into it. Third, the XML
syntax does not support imperative control structures so well. Expressing them in XML
is more clumsy and verbose than using a syntax specifically designed for that purpose.
It did not end so well for JSP. The Java community learned that there were better
approaches. First were called "Model 2" (early Struts and Spring MVC), and later
"Component Oriented Frameworks" (Wicket and JSF - JavaServer Faces). The last time
I checked I could not even find JSP in Oracle' official Java Enterprise Edition tutorial.
It is easy to ascribe the demise of JSP to the fact that it was generating HTML on the
server. However, that is only part of the problems with JSP.

The Declarative / Imperative Paradigm Mismatch


Declarative languages (such as HTML and XML) are good a modeling state such as
documents, or the overall composition of a GUI. Imperative languages (such as
JavaScript, Java, C etc.) are good a modeling operations. The syntaxes of both
declarative and imperative languages were designed to support their specific purposes.
Therefore, when you try to use a declarative language to mimic imperative mechanisms
it may work for simple cases, but as the cases get more advanced the code tend to
become clumsy. The syntax just wasn't intended for that purpose. Granted, you can
create all kinds of workarounds to make it look nicer, but that doesn't change the
underlying fact, that you are trying to use a declarative language for imperative
operations.
The same is true the other way around. Using an imperative language will often also get
clumsy. Anyone who has tried writing an HTML document using
JavaScript's document.write() function, or wired up a Java Swing GUI using Java, or an
SWT GUI for that matter, knows how clumsy this code can get.
172

When you try to use a declarative language for imperative purposes, or an imperative
language to for declarative purposes, you end up with what I call "The declarative /
imperative paradigm mismatch". This mismatch often results in clumsy or ugly code.
It is easy to think that the declarative / imperative mismatch can be avoided with a
programming language that is designed to handle both paradigms. But the problem
goes deeper than the language syntax.
It is not the syntax of a programming language that decides if the language is
declarative or imperative. It is the semantic meaning of what the language describes
that decides between declarative and imperative. You could invent a more Java-like
syntax to describe HTML elements. Or a more HTML-like syntax to describe Java
instructions. But such syntaxes would not change the fact that one language describes
state (HTML documents) and the other language describe commands (operations).
Thus, a Java-like syntax for describing HTML documents would still be declarative, and
a more HTML-like syntax for describing Java-operations would still be imperative.
Think about it for just a moment. JavaScript actually already has a declarative
mechanism built in for defining JavaScript objects. It's JSON - JavaScript Object
Notation. You could actually mimic HTML using JSON. Here is an example:
{
html:{
head:{title:"JSONmimickingHTML"},
body:{
text:"HelloWorld"
}
}
}

Of course this doesn't mimic HTML attributes or even the combination of text and HTML
elmeents possible in the body of an HTML element. But I am sure the JSON syntax
could have been extended to cover that.
173

Imagine you had to generate a JSON object using JavaScript - by mixing JavaScript
instructions in-between the JSON notation. Regardless of the JavaScript-like syntax, it
would be a hard problem to solve elegantly.
Now we are down to what the declarative / imperative paradigm mismatch is really
about. It's just hard to design one language that can both describe state and support
dynamic generation of state intertwined, regardless of the syntax. JSP is a good
example of that. The above JavaScript / JSON example is a good example of that.
XSL is another fine example of the the declarative / imperative mismatch. XSL
attempted to be a declarative language for describing XML document transformations.
Again, it worked beautifully for simple transformations, but once you got to more
advanced cases, XSL broke own. You had to resort to an imperative language for those
parts.
AngularJS is using a similar approach with its directives. AngularJS directives are either
HTML elements, attributes, CSS classes or HTML comments which trigger imperative
actions in their respective JavaScript implementations. AngularJS directives are similar
to JSP tag libraries and are thus prone to the same problems. I find it puzzling that
some developers (in the Java community at least) wrinkle their noses at JSP but praise
AngularJS. Despite the amount of rational thinking our jobs require, the IT industry is far
from always behaving rationally - but that is another topic for another article.

Finding the Declarative / Imperative Balance


There are definitely parts of a GUI which it makes sense to define using a markup
language. Markup languages are typically declarative, and declarative languages are
good at modeling state. The composition of a GUI is state. Thus, it makes sense to
model the overall composition of a GUI using a declarative language (e.g. HTML).
But there are also parts of a GUI (e.g. advanced GUI components) that have too
complex a behaviour to be sensibly defined using a declarative language like HTML. For
instance, an advanced data grid, or a tree view, or interactive graphs, or animations, or
a game. HTML is not very good at representing recursive behaviour, which makes tree
structures harder to implement. Granted, you can get around this by reducing the tree
structure to a flat list with an indentation level for each item in the list. But the point is

174

that you have to resort to workarounds to get that sort of stuff to work. HTML just wasn't
designed for imperative operations.
This diagram illustrates how a modern HTML5 / CSS3 / JavaScript GUI may contain
both simple and complex components, some of which are best defined using HTML,
and some of which are best rendered via JavaScript.

Finding the right balance between how much is done declaratively and how much is
done imperatively is not easy. Somehow we have to bridge or combine these two
paradigms. But where on the axis is the optimal balance?

As mentioned earlier I have worked with several different GUI toolkits. In my opinion
what has worked best is when you use a declarative approach for the overall

175

composition of the GUI, and use an imperative approach when rendering the more
complex GUI components. Look at this HTML template:
<html>
<head>
</head>
<body>

<div>
<div>MyApp</div>
<div><tableid="theTable"jqctype="jqcTable"></table></div>
</div>

</body>
</html>

It contains a label (MyApp) which is easily declared and positioned using HTML. And it
contains a data table which is a more complex GUI component, so only its location in
the GUI is declared in the HTML. How it is rendered, bound to data and how it behaves
when the user clicks rows etc. is implemented in JavaScript.
This model contains a clear separation between the declarative and imperative
paradigm. At least in the HTML template part. The implementations of the various
components like the data table will be more muddy. But at least that is shielded from the
developer making the HTML template. You are not tempted to specify part of it using
HTML, and part of it using HTML-like directives. And you do not have to specify the
whole GUI composition imperatively either.
The above balance is how Flex works. You can specify the overall composition of a GUI
in Flex using an XML format. You can then implement components in ActionScript which
176

can be referenced in the XML. This isn't perfect, but at my current level of insight into
GUI technologies, I feel this approach is most optimal I have seen.
In my opinion AngularJS has positioned itself a step closer to the declarative end point
than Flex. Yes, you can implement more coarse grained directives in AngularJS so you
end up with an HTML template that is similar to the above. But that was never the selling
point of AngularJS. It is usually the more fine grained directives that "Angularistas"
praise.

After realizing that AngularJS was not what I was looking for, I actually started
implementing my own GUI toolkit inspired partly Flex, and based on JavaScript and
jQuery. I will get back to that later in this article.

HTML5 Canvas & WebGL


If you plan to render part of your GUI using HTML5 canvas or WebGL, you will also not
get much help from AngularJS. Both HTML5 canvas and WebGL have imperative
interfaces. The only HTML you see is the <canvas> element they both use to draw on. In
fact, you will end up with a separation between HTML and JavaScript which is very
similar to the separation I described earlier, where the HTML only contains a reference
to where the components are located in the GUI, and not how they are rendered.

The Intrusiveness of AngularJS Directives


As already mentioned earlier, AngularJS directives are intrusive on your HTML template,
just like JSP tag libraries etc. were. In order to "teach HTML new tricks" you end up with
HTML full of non-HTML elements and attributes. Think about it for a while. When you
need to teach HTML new tricks, that is a pretty good sign it is time to change to the
imperative paradigm (JavaScript), except perhaps for very simple tricks.
177

Another example of how the templating mechanism is intrusive is when you look at how
many function calls that can (and will) be embedded in the HTML. Function calls on
the $scope object. Before AngularJS it was "best practice" to keep function calls out of
the HTML. For instance, you should not use the onclick event attributes on HTML
elements, but rather attach event listeners via JavaScript. Somehow that was forgotten
with AngularJS, and now we are back to embedding JavaScript function calls in the
HTML.

Designers Are Not Developers


One argument I have seen often in favor of more advanced HTML templating systems
is, that when no programming is involved in specifying the template, then designers can
implement the HTML templates independently from the developers. If a designer knows
HTML, then he or she will also be able to use the HTML templating system.
I encountered this argument the first time related to JSP and its tag libraries. If a
designer learned the tag libraries he or she could implement functionality without having
to bother a developer. Adobe Dreamweaver - a popular HTML design tool - even has
built-in support for JSP tag libraries. I have seen the same argument on blogs used in
favor of the AngularJS HTML template system.
I haven't actually worked in a place where this actually worked. Designers did not
implement functionality, even with HTML-like tag libraries or directives. If this works
where you are employed, I'd be happy to hear about your experiences.
In my opinion the argument is based on a false premise. The premise that if a designer
knows the HTML syntax then they can all of a sudden perform programming tasks,
given an HTML-like templating system. While this is theoretically true, the premise
mistakes syntax for semantics.
A designer is primarily concerned with looks while a developer is primarily concerned
with behaviour. If you give a designer an HTML-like syntax and asking her to add
behaviour to the web page, there is a pretty good chance that she will think "but what
does that have to do with design?". It is not what her mind is trained to do, regardless of
the syntax.
The same is true the other way around. A developer does not all of a sudden become a
designer just because they get a cool graphical API at their disposal. Looks and
178

behaviour are different semantic areas of an application. These semantics are what
separates the designer's work from the developer's - not syntax or tools.
There is a significant difference between specifying the looks and behaviour of an
application, even if the syntax used for the two tasks is the same.

AngularJS Without Directives?


AngularJS directives are one of the core features of AngularJS. Take them out, and
what do you really have left? The whole framework revolves around them and their
binding to the $scope object, the way AngularJS is designed now. Thus, if you choose to
use AngularJS in your project, the directives is a phenomenon you will have to live with.

Two-way Data Binding


Another feature that seem to impress people about AngularJS (apart from its directives),
is the two-way data binding between form fields and model properties. However, in a
real life application this is not always that useful.
AngularJS will copy the values of form fields into your model object automatically, if the
form field values are valid. If a form field is not valid, that model field is left empty. That
means, that if you bind your form fields to an object in an array which you are using to
display e.g. a data table with, those fields are cleared in the data table too. Or at least in
your data model.
You often don't want that. You only want data to be copied from form fields if they
represent a valid coherent collection of data. In other words, you don't want any data
copied into your original data unless all data in the form is valid. And you don't want any
data copied into your model if the user ends up pressing the "cancel" button.
Second, you will often not even want the data copied directly into your data objects until
the data has been sent to the server (typically using a remove create or update service),
and the server has responded that the data was accepted. Then, and only then do you
want your data model on the client updated to reflect the new values. The following
diagram illustrates this data flow:

179

The two-way data binding in AngularJS kind of gets in the way of creating this data flow.
You will end up binding your form fields to model variables that are separate from your
model data objects, to avoid polluting your data objects. That way you copy data from a
model object into form field model properties, further into form fields, then back into form
field model properties, then send them to the server, and if that succeeds, you can
update your original model data object. Here is the data flow you will end up with in
AngularJS:

180

While you can get an app to work with this data flow, it kind of takes the glamour away
from two-way data binding.

Critique Summary
We do indeed need better frameworks to make it easier to develop larger HTML /
JavaScript applications, but I don't feel that AngularJS has chosen the right approach.
We do need to find a balance between the declarative HTML and the imperative
JavaScript, but I feel that AngularJS has gone too far in the declarative direction. We do
need to find ways to bind data to HTML elements / GUI components, but the one-way
data binding in the AngularJS directives and two-way data binding in forms can be done
better. But this is just my opinion. The whole purpose of this article was to help you form
your own opinion.

An Alternative
As mentioned earlier I have been looking a long time for the "perfect" GUI toolkit, and
when AngularJS turned out not to be what I was looking for either, I finally decided to
make an attempt at a GUI toolkit myself.
181

The GUI toolkit is inspired by Flex and based on jQuery. The toolkit is centered around a
page controller which scans the HTML page for elements referencing GUI components.
For each GUI component reference found, a corresponding JavaScript object is created.
These objects (components) are then kept internally in the page controller.
The page controller helps you avoid the "jQuery soup" which often occurs in larger
jQuery apps. The page controller helps you break the code into components and
modules, and keep references to instantiated components and modules etc.
The component approach avoids the DOM-centric code you can easily end up with in
jQuery powered web apps, especially if they use jQuery plugins as GUI components.
Therefore the toolkit does not use jQuery plugins for its GUI components.
The toolkit is called jqComponents (as in jQuery Components) and can be found
at jqcomponents.com
Whether this approach will be closer to the "perfect" I am looking for than AngularJS is
too early to say. Only time will tell. The initial proof-of-concept looks promising though
(but I am biased of course).

182

Você também pode gostar