ANGULARJS
The superheroic Javascript framework.
summary
- What's a Framework?
- Why AngularJS?
- Crash course on JavaScript
- Develop your own AngularJS app:
- Variable interpolation
- Two-way data binding (model/view)
- Controllers
- Routers
- Filters
- Directives
- Building your own directives
- What makes AngularJS different from other frameworks
Why A framework?
Complex web apps


Browser is no longer a dumb terminal



Why Angular
- "What HTML would have been had it been designed for web apps"
- HTML6!
- Angular <3 JavaScript
- MVC done right | A declarative user interface | Data models are POJO | Behavior with directives | Flexibility with filters | Write less code | DOM manipulations where they belong | Service providers where they belong | Context aware communication | Unit testing ready |
<Angular />

Install (if you don't have 'em)
- Node
-
git
then....
sudo npm install -g bower
First, JavaScript basics
- Data types
- Functions
- Scope
- JavaScript & DOM
- Asynchronous Programming
Callback hell
var results = doThis(function(data) {
doThat(data, function(data2) {
mungeNumbers(data2, function(data3) {
hideTracks(data3, function(data4) {
boostProfits(data4, function(data5) {
// On, and on, and on and on...
})
})
})
})
})
Promises
var promise = new Promise(function(resolve, reject) {
resolve(1);
});
promise.then(function(val) {
console.log(val); // 1
return val + 2;
}).then(function(val) {
console.log(val); // 3
});
Let's Start!
Checkout the project, then install dependencies and run the local server
git clone --depth=14 https://github.com/angular/angular-phonecat.git
cd angular-phonecat
npm install
git checkout -f step-0
npm start //Open: http://localhost:8000/app/index.html
http://docs.angularjs.org/tutorial
0 - The boostrap
app/index.html
:
<!doctype html>
<html lang="en" ng-app>
<head>
<meta charset="utf-8">
<title>My HTML File</title>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
<link rel="stylesheet" href="css/app.css">
<script src="bower_components/angular/angular.js"></script>
</head>
<body>
<p>Nothing here {{'yet' + '!'}}</p>
</body>
</html>
git checkout -f step-0
Things to remember
- Angular performs DOM compilation
<p>1 + 2 = {{ 1 + 2 }}</p>
- Creates scopes

My Working directory


1 - Browser readable html
AngularJS works with pure HTML directly. No need of ugly string-parsed template engines (Handlebars, Mustache, etc)
app/index.html
:
<ul> <li> <span>Nexus S</span> <p> Fast just got faster with Nexus S. </p> </li> <li> <span>Motorola XOOM™ with Wi-Fi</span> <p> The Next, Next Generation tablet. </p> </li> </ul>
git checkout -f step-1
2- Angular templates
In Angular, the view is a projection of the model through the HTML template
app/index.html
:
<html ng-app="phonecatApp">
<head>
...
<script src="bower_components/angular/angular.js"></script>
<script src="js/controllers.js"></script>
</head>
<body ng-controller="PhoneListCtrl">
<ul>
<li ng-repeat="phone in phones">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
</body>
</html>
git checkout -f step-2
Model and Controller
The data model (a simple array of phones in object literal notation) is now instantiated within the PhoneListCtrl controller. The controller is simply a constructor function that takes a $scope parameter:
app/js/controllers.js
:
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope) {
$scope.phones = [
{'name': 'Nexus S',
'snippet': 'Fast just got faster with Nexus S.'},
{'name': 'Motorola XOOM™ with Wi-Fi',
'snippet': 'The Next, Next Generation tablet.'},
{'name': 'MOTOROLA XOOM™',
'snippet': 'The Next, Next Generation tablet.'}
];
});
$Scope
A scope can be seen as the glue which allows the template, model and controller to work together.
Keeps the template, data model, and controller in sync.
3 - Filters
app/index.html
:
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
Search: <input ng-model="query">
</div>
<div class="col-md-10">
<!--Body content-->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query">
{{phone.name}}
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</div>
</div>
git checkout -f step-3
Filtering Repeaters
<li ng-repeat="phone in phones | filter:query">
The filter function uses the [[query]] value to create a new array that contains only those records that match the query.
4 - Two way data binding
app/index.html
:
Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
<option value="name">Alphabetical</option>
<option value="age">Newest</option>
</select>
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp">
<span>{{phone.name}}</span>
<p>{{phone.snippet}}</p>
</li>
</ul>
git checkout -f step-4
Angular creates a two way data-binding between the <select > element and the [[orderProp]] model. [[orderProp]] is then used as the input for the orderBy filter.
Did you notice?
No bloated DOM manipulation code is necessary!
5 - XHR & Dependency Injection
So, we have a small API serving...
[
{
"age": 13,
"id": "motorola-defy-with-motoblur",
"name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
"snippet": "Are you ready for everything life throws your way?"
...
},
...
]
what's a JSON anyways?
git checkout -f step-5
Consuming XHR
Remember jQuery's $.ajax calls?
We'll use Angular's $http service in our controller to make an HTTP request
app/js/controllers.js:
var phonecatApp = angular.module('phonecatApp', []);
phonecatApp.controller('PhoneListCtrl', function ($scope, $http) {
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
$scope.orderProp = 'age';
});
Dependency injection
Bringing the dependencies (helpers/plugins/modules/whatever) you need in your controller
But why dependency injection?
- Modularization (encapsulation)
-
Importing modules
- File Minification
6. More about templates
app/phones/phones.json
(sample snippet):
[
{
...
"id": "motorola-defy-with-motoblur",
"imageUrl": "img/phones/motorola-defy-with-motoblur.0.jpg",
"name": "Motorola DEFY\u2122 with MOTOBLUR\u2122",
...
},
...
]
app/index.html
:
... <ul class="phones"> <li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail"> <a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a> <a href="#/phones/{{phone.id}}">{{phone.name}}</a> <p>{{phone.snippet}}</p> </li> </ul> ...
git checkout -f step-6
ngSrc
ng-src directive prevents the browser from treating the Angular {{ expression }} markup literally, and initiating a request to an invalid URL
url http://localhost:8000/app/{{phone.imageUrl}}
7. Router
hurray for one-page applications

git checkout -f step-7
Routing & Multiple Views
app/index.html
:
<!doctype html>
<html lang="en" ng-app="phonecatApp">
<head>
...
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/app.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<div ng-view></div>
</body>
</html>
The new app
app/js/app.js
:
var phonecatApp = angular.module('phonecatApp', [ 'ngRoute', 'phonecatControllers' ]);
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
Multiple views...
app/partials/phone-list.html
:
<div class="container-fluid">
<div class="row">
<div class="col-md-2">
<!--Sidebar content-->
Search: <input ng-model="query">
Sort by:
<select ng-model="orderProp">
<option value="name">Alphabetical</option>
<option value="age">Newest</option>
</select>
</div>
<div class="col-md-10">
<!--Body content-->
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
</ul>
</div>
</div>
</div>
Multiple controllers...
app/js/controllers.js
:
var phonecatControllers = angular.module('phonecatControllers', []); phonecatControllers.controller('PhoneListCtrl', ['$scope', '$http', function ($scope, $http) { $http.get('phones/phones.json').success(function(data) { $scope.phones = data; }); $scope.orderProp = 'age'; }]); phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', function($scope, $routeParams) { $scope.phoneId = $routeParams.phoneId; }]);
...and the router
...
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
As we saw, the router wired URL patterns to certain controllers and views
8 - More Templating
Implementing the phone details view, which is displayed when a user clicks on a phone in the phone list.
git checkout -f step-8
Expanding the PhoneDetailCtrl by using the $http service to fetch the json files.
app/js/controllers.js
:
var phonecatControllers = angular.module('phonecatControllers',[]);
phonecatControllers.controller('PhoneDetailCtrl', ['$scope', '$routeParams', '$http',
function($scope, $routeParams, $http) {
$http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
$scope.phone = data;
});
}]);
Template
app/partials/phone-detail.html
:
<img ng-src="{{phone.images[0]}}" class="phone">
<h1>{{phone.name}}</h1>
<p>{{phone.description}}</p>
<ul class="phone-thumbs">
<li ng-repeat="img in phone.images">
<img ng-src="{{img}}">
</li>
</ul>
<ul class="specs">
<li>
<span>Availability and Networks</span>
<dl>
<dt>Availability</dt>
<dd ng-repeat="availability in phone.availability">{{availability}}</dd>
</dl>
</li>
...
<li>
<span>Additional Features</span>
<dd>{{phone.additionalFeatures}}</dd>
</li>
</ul>
Title
9 - Filters
Formatting values:
12121212 -> $12,121,212.00
pepe PEcas Picapiedra -> Pepe Pecas Picapiedra
git checkout -f step-9
{{ expression | filter }}
app/partials/phone-detail.html
:
...
<dl>
<dt>Infrared</dt>
<dd>{{phone.connectivity.infrared | checkmark}}</dd>
<dt>GPS</dt>
<dd>{{phone.connectivity.gps | checkmark}}</dd>
</dl>
...
Creating a filter...
app/js/filters.js
:
angular.module('phonecatFilters', []).filter('checkmark', function() { return function(input) { return input ? '\u2713' : '\u2718'; }; });
app/js/app.js
:
...
angular.module('phonecatApp', ['ngRoute','phonecatControllers','phonecatFilters']);
...
10 - Event Handlers
Adding a click event
git checkout -f step-10
jQuery
<img ng-src="{{img}}" class="img-clickable">
$( ".img-clickable" ).click(function() {
alert( "Handler for .click() called." );
});
AngularJS
<img ng-src="{{img}}" ng-click="setImage(img)">
11 - REST and Custom Services
Defines a custom service that represents a RESTful client. Using this client we can make requests to the server for data in an easier way:
-
$http API
-
HTTP methods
-
URLs
git checkout -f step-11
But first...
What's a factory?
Service
app/js/services.js
.
var phonecatServices = angular.module('phonecatServices', ['ngResource']);
phonecatServices.factory('Phone', ['$resource',
function($resource){
return $resource('phones/:phoneId.json', {}, {
query: {method:'GET', params:{phoneId:'phones'}, isArray:true}
});
}]);
Now we have
$scope.phones = Phone.query();
instead of
$http.get('phones/phones.json').success(function(data) {
$scope.phones = data;
});
Directives
<date-picker></date-picker>
<input type="text" date-picker/>
<input type="text" class="date-picker"/>
<!--directive:date-picker-->
Fun time with directives
To-do miniapp:
Currency live converter:
Directive definition object
Full docs in https://docs.angularjs.org/guide/directive
var app = angular.module('myapp', []);
app.directive('helloWorld', function() {
return {
restrict: 'AE',
replace: 'true',
template: '<div>Hello World!!</div>'
};
});
ExAmple
<mayuscula model="query"></mayuscula>
directivas.directive('mayuscula', function() {
return {
restrict: 'E',
scope: {'model': '='},
link: function($scope, element, attr){
$scope.$watch('model', function(newVal, oldVal){
if (newVal !== oldVal) {
$scope.model = newVal.toUpperCase();
}
});
}
};
});
What makes angular different?
The most important thing
Angular implements its own digest cycle


Angularjs
By Erick Mendoza
Angularjs
AngularJS The Superheroic JavaScript framework
- 1,531