AngularJS Framework : Data Binding and Controllers (Todo App)
In this tutorial, we'll make an Todo App which uses data binding and controller.
Data-binding is a way of updating the view automatically whenever the model changes, as well as updating the model whenever the view changes. This eliminates DOM manipulation from the list of things we have to worry about.
Controllers are the behavior behind the DOM elements. AngularJS lets us express the behavior in a clean readable form without the usual boilerplate of updating the DOM, registering callbacks or watching model changes.
Here is our Todo App:
index.html:
<!doctype html> <html ng-app="todoApp"> <head> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script> <script src="todo.js"></script> <link rel="stylesheet" href="todo.css"> </head> <body> <h2>My Todo List</h2> <div ng-controller="TodoListController as todoList"> <span>{{todoList.remaining()}} of {{todoList.todos.length}} remaining</span> [ <a href="" ng-click="todoList.archive()">archive</a> ] <ul class="unstyled"> <li ng-repeat="todo in todoList.todos"> <input type="checkbox" ng-model="todo.done"> <span class="done-{{todo.done}}">{{todo.text}}</span> </li> </ul> <form ng-submit="todoList.addTodo()"> <input type="text" ng-model="todoList.todoText" size="30" placeholder="add new todo here"> <input class="btn-primary" type="submit" value="add"> </form> </div> </body> </html>
Here are the descriptions for some of the index.html code:
- ng-app: Tells AngularJS to be active in this portion of the page. In this case the entire document.
- angular.min.js: Load AngularJS.
- todo.js: App's behavior lives in JavaScript controllers.
- ng-controller: The behavior of content under this element will be managed using the TodoController class defined in todo.js.
- ng-click: Instead of registering event-handlers, we declare which method on the controller to call. Here clicking the link will call archive() method.
- ng-repeat: We're using ng-repeat to unroll a collection. Here, for every object in todos, AngularJS will create new copy of the <li> element. When objects are added to the todos collection the ng-repeat automatically adds new <li> elements into the DOM. Similarly when the objects are removed from todos then the corresponding <li> element is removed as well. This is one of the most versatile directives in AngularJS.
- ng-model: This links the form and the model. This means that any changes to the control update the data in our model, and when we change the model it updates the control. AngularJS automatically copies the state of the checkbox into todo.done. Conversely, if we update todo.done we will see the checkbox respond accordingly.
- {{todo.done}}: To show strike-throughs for completed tasks we have created a CSS class done-true. When the todo.done is true the resulting CSS selector is done-true which then applies the strikethrough.
- ng-submit: Intercepts form submission and instead calls addTodo(). Inside this method we read the todoText property and insert it into the todos collection.
todo.js:
angular.module('todoApp', []) .controller('TodoListController', function() { var todoList = this; todoList.todos = [ {text:'Todo #1', done:true}, {text:'Todo #2', done:false}, {text:'Todo #3', done:false}, {text:'Todo #4', done:false}]; todoList.addTodo = function() { todoList.todos.push({text:todoList.todoText, done:false}); todoList.todoText = ''; }; todoList.remaining = function() { var count = 0; angular.forEach(todoList.todos, function(todo) { count += todo.done ? 0 : 1; }); return count; }; todoList.archive = function() { var oldTodos = todoList.todos; todoList.todos = []; angular.forEach(oldTodos, function(todo) { if (!todo.done) todoList.todos.push(todo); }); }; });
Here are the descriptions for some of the todo.js code:
- TodoListController: The controller is the code behind the view. We can clearly see our application behavior because there is no DOM manipulation or framework specific boilerplate. Just simple, readable JavaScript.
- todos: We are creating the model with two initial todo items. Notice that we simply assign our model to the $scope and AngularJS reflects the state in the UI automatically. The model data is a Plain-Old-JavaScript-Object no need to wrap it in proxy or accesses the property through special setter methods.
- addTodo: We are assigning the behavior into the $scope so that the ng-submit can invoke it.
- push: This is just the Array.push method. Calling it updates the model, which then updates the view through data-binding. The ng-repeat is bound to this array. It automatically unrolls the array and adds the new DOM element into the view.
- remaining: This is a computed property. No need to define its dependencies or worry about when it needs to be updated.
todo.css:
.done-true { text-decoration: line-through; color: grey; }
The done-true adds strikethrough decoration when the task is done.
AngularJS
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization