Category Archives: Angular Tutorial

Angular tutorial – todo list breakdown

AngularJS’s main website, Angularjs.org, has a to-do list example on the first page. It’s a nifty introduction to Angular with examples of “data-binding,” one of the key Angular concepts (other goodies like routers and modules to come in later posts). Here I’ll provide an breakdown of how it is put together. Please note – this analysis follows more along the line of the video they provide for the to-do list example, which is just slightly different.

The code consists of two core files (index.html and controllers.js), along with all the supporting javascript files for console logging, Angular, jQuery, underscore.js and a bit of CSS provided by the Bootstrap UI library.

Here is the index.html code I used:

<html ng-app>
	<head>
		<script type="text/javascript" src="consoleLog.js"></script>
		<script type="text/javascript" src="underscore-min.js"></script>
		<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
		<script type="text/javascript" src="angular.min.js"></script>
		<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
		<link rel="stylesheet" href="bootstrap/css/bootstrap.css">

		<script type="text/javascript" src="controllers.js"></script>
 	</head>

	<body ng-controller="todoController">
		Total todos: {{returnTotalTodos()}} 
		<ul class="unstyled">
			<li>testing</li>
			<li ng-repeat="todo in todos"><input type="checkbox" ng-model="todo.done" ng-click="handleTodoCheck()">{{todo.todoItem}}</li>
		</ul>

		<input type="text" ng-model="newTodoText" ng-model-instant ><button ng-click="addNewTodo()"><i class="icon-plus"></i>add one</button> {{newTodoText}}

		<div>
			<button ng-click="clearFinishedTodos()">Clear Finished Todos</button>
		</div>

	</body>

</html>

Let’s break that down a bit… first the beginning bits.

<html ng-app>
	<head>
		<script type="text/javascript" src="consoleLog.js"></script>
		<script type="text/javascript" src="underscore-min.js"></script>
		<script type="text/javascript" src="jquery-1.10.1.min.js"></script>
		<script type="text/javascript" src="angular.min.js"></script>
		<script type="text/javascript" src="controllers.js"></script>
		<script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
		<link rel="stylesheet" href="bootstrap/css/bootstrap.css">

		<!-- we got 5 lines of CSS in this tiny example app. So I'm inlining it! -->
		<style> 
		.done-true {
  			text-decoration: line-through;
  			color: grey;
		}
		</style>
 	</head>

We first activated Angular across the app using the “ng-app” directive inside the html tag. This wakes up Angular and makes it pay attention to everything between the opening and closing tags. Without that, no Angular.

Next we load up our javascript files. The first line loads up consoleLog.js which gives me a snippet of special console logger code I use on various projects. The reason why I initialize the console this way is because Internet Explorer handles the console.log function inconsistently depending on the IE version and other factors, so I throw in some boilerplate. I have a page where I describe how to handle the flaky console log in Internet Explorer.

Next I load up all the Javascript libraries including the most recent versions of underscore.js, jQuery, Angular and Bootstrap. I follow up by loading the controller file for this MVC (Model-View-Controller) app, which along with the index.html is the second custom-written file. Finally, I inline the 5 lines of custom CSS code we are going to use. Now some people object to inlining any CSS code; for this sake of this tiny demo app, and to avoid creating a tiny CSS file to download, I’ve chosen a simpler route. In a full professional application with more complex CSS, you should create separate CSS files.

After that follows the meat of the index.html:

	<body ng-controller="todoController">
		Total todos: {{returnTotalTodos()}} 
		<ul class="unstyled">
			<li ng-repeat="todo in todos"><input type="checkbox" ng-model="todo.done">
                          <span class="done-{{todo.done}}">{{todo.todoItem}}</span>
                        </li>
		</ul>

		<input type="text" ng-model="newTodoText" ng-model-instant ><button ng-click="addNewTodo()"><i class="icon-plus"></i>add one</button> {{newTodoText}}

		<div>
			<button ng-click="clearFinishedTodos()">Clear Finished Todos</button>
		</div>

	</body>

</html>

What’s going on here:
1. inside the body tag, we use the ng-controller directive to specify which controller code will be in charge (until the /body tag). Remember: the controller code is the Angularized code necessary to mediate between the Model and the View in our MVC (Model-View-Controller) app. Microtutorial: in an MVC app, the Model is the chunk of code/data that represents the “real world” objects in your app; the View is the visual stuff you see on screen that lets you interact with some representation of the Model (which might adapt responsively between a tiny mobile screen versus a big desktop screen); and the Controller is the glue code that separates and sets up communication between the Model and View, giving you the ability to re-use the Model with multiple View configurations (super important in a multi-device world where the Views are going to vary considerably depending on which device a user uses to access your app).

2. A very funny looking, non-HTML {{returnTotalTodos()}} references a function within our controller code that will update automagically to let us know the total count of todo list items. We’ll get to it soon!

3. We create a list using ul and li elements… The li elements are repeated for each todo item we have. We do this with the ng-repeat directive, our great cycling directive, which we’ll use to loop through the todos Model array defined in our controller code.

Let’s take a quick preview of the actual todos array (a starter todo list we use for the sake of example) defined in the controller. Don’t worry about the “$scope” business for now. We’ll see more of this later. For now — it’s just a basic Javascript object, with a todoItem field containing the text of each specific todo item, and a done field describing it’s status as complete (true) or incomplete (false).

	$scope.todos = [
		{todoItem: 'walk the dog', done: false},
		{todoItem: 'feed the cat', done: false}
	];

Back in our index.html file, the ng-repeat directive works as follows: when we specify

ng-repeat="todo in todos"

… Angular will find the “todos” array in our controller (it knows which controller to reference because we are within the body tag where it was first specified) and will loop through it object-by-object and will successively assign each object to the todo variable as it cycles through the loop. So what will happen here is that the li tag will be produced once for every object in the todo list, and each time we loop through li tags, we’ll have a different todo object to use for our data.

The ng-model=”todo.done” sets up a two-way data binding between the view and the model for this todo item. Simply using the ng-model directive, we create an automagic connection between the checkbox state (true/false) and the value of the done field (a mirrored true/false). This data-binding is one of the great benefits of Angular versus a regular framework like jQuery: we can save ourselves a lot of work, and make our code significantly simpler to follow, because we don’t have to directly manipulate the DOM (Document Object Model — the abstract page structure described by the HTML) in order to connect events in the View (e.g. clicking the checkbox) with the corresponding value of a data field in the Model (e.g. the value of the done field for this particular todo item). We did not even have to set up a click-event handler for this particular case — I did mention it was automagic, right?

Let’s add a field and button for new todo items:

<input type="text" ng-model="newTodoText" ng-model-instant ><button ng-click="addNewTodo()"><i class="icon-plus"></i>add one</button>

The ng-model=”newTodoText” directive here creates a two-way binding between the value of the text input, and the newTodoText model variable “inside” the scope of todoController controller (you remember — the one we referenced in the body tag). The ng-model-instant directive ensures it is updated in real time. In the “add one” button, we use the ng-click directive to bind the click event with the addNewTodo() function defined in the controller. The and tags add a bit of CSS prettiness — they give us a nice plus icon courtesy of the icon-plus class defined by Bootstrap. The addNewTodo() will, as you may have guessed, execute the logic necessary to add this newly inputted todo item to the array of todos.

Finally we throw in a button to delete the completed todos from our list. This will trigger a function in our controller to do the actual cleanup of the todo array — when that executes, we’ll see the results instantly reflected in our view in the form of a cleaned up list. A simple ng-click directive ties the button together with the corresponding function in the controller.

		<div>
			<button ng-click="clearFinishedTodos()">Clear Finished Todos</button>
		</div>

OK. That’s the index.html file. The controllers.js file contains our controller code and serves as the brain of the application. Here’s the source for the controller.js file and we’ll go through it bit by bit:


function todoController($scope) {

	$scope.todos = [
		{todoItem: 'walk the dog', done: false},
		{todoItem: 'feed the cat', done: false}
	];
    
    $scope.returnTotalTodos = function () {
    	console.log ('returnTotalTodos executes');
    	return $scope.todos.length;
    }


    $scope.addNewTodo = function () {
    	 console.log ('addNewTodo executes');
    	         var nothing = $scope.todos.length;
    	         var nothing2  = nothing;
    	if ($scope.newTodoText.length){
    		$scope.todos.push ( {todoItem: $scope.newTodoText , done: false});
    		$scope.newTodoText = '';
    	}

   
    }

    $scope.clearFinishedTodos = function () {
    	console.log ('clearFinishedTodos executes');
    	$scope.todos = _.filter($scope.todos, function (todo) {return !todo.done})
    }

}

First we start with the line

function todoController($scope) {

Looks simple. Is simple. Yet deceivingly powerful. The todoController is the name of our controller referenced from the body tag in the html. It’s got to be the same name — that’s how Angular associates the ng-controller we specified with the actual controller code function. And the $scope reference passed in is super-important. This is data structure passed in by Angular which sets the entire stage for dependency injection. Dependency Injection (DI) is one of the core concepts of Angular JS’s approach to MVC. What DI does is pass in to the controller code the “glue” data structure that sets the context and scope for all variables and functions inside the controller. Angular is a very clean system — it allows us to run multiple Angular apps on the same page, all potentially with different controllers. And while there are many levels to DI, the most direct and straightforward explanation here is that we pass in a data structure (called $scope) which is going to hold all other model variables and controller functions within it. Angular has NO global scope — it uses dependency injection to allow us to operate clean namespaces so we can use all our other libraries (jQuery, Yahoo YUI, etc) without fear of namespace overlap (and the corresponding chaos that would ensue).

All our variables and functions inside the controller will be included within $scope, as we shall see. And since Angular monitors $scope for us later, this dependency injection process enables the automagic processes necessary for two-way data binding between Views and Models.

Again – there is more to dependency injection both in general and as it applies to Angular – but that’s a sufficient basis for understanding for now.

This tutorial will be continued in a few days… Thanks for tuning in!