Your First AngularJS App: Creating and Using Controller Behaviors

Controllers define behaviors on the scope. Behaviors are functions that operate on the data in the model to implement the business logic in the application. The behaviors defined by a controller support a view to display data to the user and to update the model based on user interactions.

To demonstrate a simple behavior, I am going to change the label displayed to the right of the header in todo.html so that it displays only the number of incomplete to-do items. You can see the changes required to do this in Listing 2-7. (I also removed the column that contains the true and false values, which I required only to demonstrate that data bindings reflected changes in the data model.)

Listing 2-7. Defining and Using a Controller Behavior in the todo.html File

<!DOCTYPE html>

<html ng-app=”todoApp”>

<head>

<title>TO DO List</title>

<link href=”bootstrap.css” rel=”stylesheet” />

<link href=”bootstrap-theme.css” rel=”stylesheet” />

<script src=”angular.js”></script>

<script>

var model = {

user: “Adam”,

items: [{ action: “Buy Flowers”, done: false },

{ action: “Get Shoes”, done: false },

{ action: “Collect Tickets”, done: true },

{ action: “Call Joe”, done: false }]

};

var todoApp = angular.module(“todoApp”, []);

todoApp.controller(“ToDoCtrl”, function ($scope) {

$scope.todo = model;

$scope.incompleteCount = function () {

var count = 0;

angular.forEach($scope.todo.items, function (item) {

if (!item.done) { count++ }

});

return count;

}

});

</script>

</head>

<body ng-controller=”ToDoCtrl”>

<div class=”page-header”>

<h1>

{{todo.user}}’s To Do List

<span class=”label label-default” ng-hide=”incompleteCount() == 0″>

{{incompleteCount()}}

</span>

</h1>

</div>

<div class=”panel”>

<div class=”input-group”>

<input class=”form-control” />

<span class=”input-group-btn”>

<button class=”btn btn-default”>Add</button>

</span>

</div>

<table class=”table table-striped”>

<thead>

<tr>

<th>Description</th>

<th>Done</th>

</tr>

</thead>

<tbody>

<tr ng-repeat=”item in todo.items”>

<td>{{item.action}}</td>

<tdxinput type=”checkbox” ng-model=”item.done” /></td>

</tr>

</tbody>

</table>

</div>

</body>

</html>

Behaviors are defined by adding functions to the $scope object that is passed to the controller function. In the listing, I have defined a function that returns the number of incomplete items, which I determine by enumerating the objects in the $scope.todo.items array and counting the ones whose done property is false.

Tip I used the angular.forEach method to enumerate the contents of the data array. AngularJS includes some useful utility methods that supplement the JavaScript language. I describe the utility methods in Chapter 5.

The name of the property used to attach the function to the $scope object is used as the behavior name. My behavior is called incompleteCount, and I can invoke it within the scope of the ng-controller attribute, which applies the controller to the HTML elements that form the view.

I have used the incompleteCount behavior twice in Listing 2-7. The first is as a simple data binding to display the number of items, as follows:

<span class=”label label-default” ng-hide=”incompleteCount() == 0″>

{{incompleteCount()}}

</span>

Notice that I call the behavior using parentheses. You can pass objects as arguments to behaviors, which makes it possible to create general-purpose behaviors that can be used with different data objects. My application is sufficiently simple that I decided not to pass any arguments and instead get the data I require directly from the $scope object in the controller.

I also used the behavior in conjunction with a directive, like this:

<span class=”label default” ng-hide=”incompleteCount() == 0“>

{{incompleteCount()}}

</span>

The ng-hide directive will hide the element it is applied to—and its content elements—if the expression that is assigned as the attribute value evaluates to true. In this case, I call the incompleteCount behavior and check to see whether the number of incomplete items is zero; if it is, then the label that displays the number of items on the list is hidden from the user.

Tip The ng-hide directive is only one of a broad set of directives that manipulate the browser Document Object Model (DOM) automatically based on the state of the AngularJS model. I get into the detail of these directives in Chapter 11 and show you how to create your own directives in Chapters 15-17.

You can see the effect of the behavior and its application by using the browser to navigate to the todo.html file, as shown in Figure 2-6. Checking and unchecking items on the list changes the number of items displayed by the counter label, and checking all of the items causes the counter to be hidden.

Source: Freeman Adam (2014), Pro AngularJS (Expert’s Voice in Web Development), Apress; 1st ed. edition.

Leave a Reply

Your email address will not be published. Required fields are marked *