Thursday, 6 November 2014

Introduction to AngularJS - Part 5

Directives

One of the best parts of Angular is that you can write your templates as HTML. You can
do this because at the core of the framework we’ve included a powerful DOM trans‐
formation engine that lets you extend HTML’s syntax.

Angular comes with many directives that help you define the view for your app. We’ll
see more of them soon. These directives can define what we commonly view as the
template. They can declaratively set up how your application works or be used to create
reusable components.
And you’re not limited to the directives that Angular comes with. You can write your
own to extend HTML’s template abilities to do anything you can dream of.




Shopping Cart Example

Let’s look at a slightly larger example that shows off a bit more of Angular. Let’s imagine
that we’re going to build a shopping app. Somewhere in the app we’ll need to show the
user’s shopping cart and let him edit it. Let’s skip straight to that part.

<html ng-app='myApp'>
<head>
 <title>Your Shopping Cart</title>
</head>
<body ng-controller='CartController'>
 <h1>Your Order</h1>
 <div ng-repeat='item in items'>
 <span>{{item.title}}</span>
 <input ng-model='item.quantity'>
 <span>{{item.price | currency}}</span>
 <span>{{item.price * item.quantity | currency}}</span>
 <button ng-click="remove($index)">Remove</button>
 </div>
 <script src="angular.js"></script>

 <script>
 function CartController($scope) {
 $scope.items = [
 {title: 'Paint pots', quantity: 8, price: 3.95},
 {title: 'Polka dots', quantity: 17, price: 12.95},
 {title: 'Pebbles', quantity: 5, price: 6.95}
 ];
 $scope.remove = function(index) {
 $scope.items.splice(index, 1);
 }
 }
 </script>
 </body>
</html>

The following is a brief tour of what’s going on here. The rest of the book is dedicated
to a more in-depth explanation.
Let’s start at the top:

<html ng-app>

The ng-app attribute tells Angular which parts of the page it should manage. Since we’ve
placed it on the <html> element, we’re telling Angular that we want it to manage the
whole page. This will often be what you want, but you might want to place it on a <div>
within the app if you’re integrating Angular with an existing app that uses other methods
to manage the page.

<body ng-controller='CartController'>

In Angular, you manage areas of the page with JavaScript classes called controllers. By
including a controller in the body tag, I’m declaring that CartController will manage
everything between <body> and </body>.

<div ng-repeat='item in items'>

The ng-repeat says to copy the DOM inside this <div> once for every element in an
array called items. On every copy of the div, it will also set a property named item to the
current element so we can use it in the template. As you can see, this results in three
<div>s each, containing the product title, quantity, unit price, total price, and a button
to remove the item entirely.

<span>{{item.title}}</span>

As we showed in the “Hello, World” example, data binding via {{ }} lets us insert the
value of a variable into part of the page and keep it in sync. The full expression
{{item.title}} retrieves the current item in the iteration and then inserts the contents
of that item’s title property into the DOM.

<input ng-model='item.quantity'>


The ng-model definition creates data binding between the input field and the value of
item.quantity.The {{ }} in the <span> sets up a one-way relationship that says “insert a value here.”
We want that effect, but the application also needs to know when the user changes the
quantity so it can change the total price.

We’ll keep changes in sync with our model by using ng-model. The ng-model declaration
inserts the value of item.quantity into the text field, but it also automatically updates
item.quantity whenever the user types a new value.

<span>{{item.price | currency}}</span>
<span>{{item.price * item.quantity | currency}}</span>


We want the unit price and total price to be formatted as dollars. Angular comes with
a feature called filters that lets us transform text, and there’s a bundled filter called
currency that will do this dollar formatting for us. We’ll look at filters more in the next
post.

<button ng-click='remove($index)'>Remove</button>

This allows users to remove items from their carts by clicking a Remove button next to
the product. We’ve set it up so that clicking this button calls a remove() function. We’ve
also passed in $index, which contains the iteration number of the ng-repeat, so we
know which item to remove.

function CartController($scope) {

This CartController manages the logic of the shopping cart. We’ll tell Angular that
the controller needs something called $scope by putting it here. The $scope is what lets
us bind data to elements in the UI.

$scope.items = [
 {title: 'Paint pots', quantity: 8, price: 3.95},
 {title: 'Polka dots', quantity: 17, price: 12.95},
 {title: 'Pebbles', quantity: 5, price: 6.95}
];


By defining $scope.items, I’ve created a dummy data hash to represent the collection
of items in the user’s shopping cart. We want to make them available to data bind with
the UI, so we’ll add them to $scope.

Of course, a real version of this can’t just work in memory, and will need to talk to a
server to properly persist the data. We’ll get to that in later post.
$scope.remove = function(index) {
 $scope.items.splice(index, 1);
}
We want the remove() function available to bind in the UI, so we’ve added this to $scope
as well. For the in-memory version of the shopping cart, the remove() function can just
delete items from the array. Because the list of <div>s created by ng-repeat is databound, the list automatically shrinks when items disappear. Remember, this remove()
function gets called from the UI whenever the user clicks on one of the Remove buttons.



No comments:

Post a Comment