AngularJS: How to write a simple To Do app

In this article I will describe how to create a simple “To Do” app in AngularJS and write about some of the basic concepts of AngularJS. The app I will be describing looks like this:

See the Pen AngularJS Simple To Do App by Chris Nielsen (@Chris_Nielsen) on CodePen.0

 

Step 1: AngularJS CDN

To create an AngularJS app, the first thing you will need is a CDN in the script portion of your HTML document.

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>

The two most important parts of this app are the HTML and the JavaScript. Here is what the HTML looks like:

  <div ng-app="ToDo" ng-controller="todoController">
      <form name="todoform" ng-submit="addTodo()" class="form-style">

        <input type="text" name="newTodo"
                           ng-model="newTodo"
                           class="text-field"
                           placeholder="Type to do item here:">
        <button ng-disabled="todoform.$invalid" class"btn-style">Add</button>

      </form>
      <br>
      <h2>To Do List:</h2>
      <div class="list-box">
        <ul>
          <li ng-repeat="todo in todos">
            <input type="checkbox" ng-model="todo.done"/>
            <span ng-class="{'done': todo.done}">{{todo.title}}</span>
          </li>
        </ul>
      </div>
      <button ng-click="clearCompleted()">Clear Completed</button>
  </div>

And here is the JavaScript:

  let app = angular.module('ToDo', []);
  app.controller('todoController', ['$scope', function($scope) {
    $scope.todos = [
      {'title':'Sample List Item', 'done': false }
    ];
    $scope.addTodo = function(){
      if($scope.newTodo){
        $scope.todos.push({'title': $scope.newTodo, 'done': false})
      }
      $scope.newTodo = ''
    }
    $scope.clearCompleted = function() {
      $scope.todos = $scope.todos.filter(function(item){
        return !item.done

      })
    }
  }])

 

Step 2: Name the app in both HTML and JS

In the HTML, we name the app with ng-app="ToDo" like so:

<div ng-app="ToDo" ...

This corresponds to this line in the JavaScript:

let app = angular.module('ToDo', []);

The HTML tag is “ng-app”. “ng” stands for “Angular”. In the JavaScript, we set up an app variable and call the angular.module() method with two arguments. The first argument is the name of the app. In this case “ToDo”.

For more information about ng-app, see:
https://www.w3schools.com/angular/ng_ng-app.asp
https://docs.angularjs.org/api/ng/directive/ngApp

For more information about angular.module(), see:
https://www.w3schools.com/angular/angular_modules.asp
https://docs.angularjs.org/api/ng/function/angular.module

 

Step 3: Set up the controller

In the HTML, the controller is set up with ng-controller="todoController" like so:

<div ... ng-controller="todoController">

This corresponds to this line in the JavaScript:

app.controller('todoController', ['$scope', function($scope) {

The HTML tag is “ng-controller”. In the JavaScript, we use the app variable and call the controller() method with two arguments. The first argument is the name of the controller that was defined in the HTML. In this case “todoController”. The second argument is an array, with the first argument being “$scope” and the second being the body of the “todoController” function.

For more information about ng-controller, see:
https://www.w3schools.com/angular/angular_controllers.asp
https://docs.angularjs.org/api/ng/directive/ngController

Here is what w3schools says about angular controllers:

The ng-controller=”myCtrl” attribute is an AngularJS directive. It defines a controller.

The myCtrl function is a JavaScript function.

AngularJS will invoke the controller with a $scope object.

In AngularJS, $scope is the application object (the owner of application variables and functions).

 

Step 4: Specify a function to run when the form is submitted

In the HTML we set up a form with an “ng-submit” tag: ng-submit="addTodo()"

<form name="todoform" ng-submit="addTodo()" class="form-style">

This specifies what controller function to run when the form is submitted. "addTodo()" corresponds to the $scope.addTodo function definition in the controller portion of the Angular code:

$scope.addTodo = function(){
 if($scope.newTodo){
  $scope.todos.push({'title': $scope.newTodo, 'done': false})
 }
  $scope.newTodo = ''
}

For more information about ng-submit, see:
https://www.w3schools.com/angular/ng_ng-submit.asp
https://docs.angularjs.org/api/ng/directive/ngSubmit

 

Step 5: Bind the form input to the angular controller using ng-model

Here is what w3schools says about Angular’s ng-model directive:

The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.

In the HTML form, the data “newTodo” is defined in ng-model. This is the text input typed by the user in the text field. This is essentially a pipeline from the web page to the Angular controller.

<input type="text" name="newTodo" ng-model="newTodo" class="text-field" placeholder="Type to do item here:">

The Angular controller defines what happens to this data when the addTo function is called:

$scope.addTodo = function(){
  if($scope.newTodo){
     $scope.todos.push({'title': $scope.newTodo, 'done': false})
  }
  $scope.newTodo = ''
}

If $scope.newTodo is present, (meaning something was typed into the text field before the user clicked the “Add” button), then assign the text as a value to the ‘title’ key in a small object and push that object into an array called ‘todos’.  This array of objects is also defined in the controller:

$scope.todos = [
  {'title':'Sample List Item', 'done': false }
];

For more information about ng-model, see:
https://www.w3schools.com/angular/angular_model.asp
https://docs.angularjs.org/api/ng/directive/ngModel

 

Step 6: Display the output in the web app

When a ‘newTodo’ item is added to the list from Step 5 above, it is displayed in the HTML immediately because of this HTML:

<ul>
  <li ng-repeat="todo in todos">
	<input type="checkbox" ng-model="todo.done"/>
	<span ng-class="{'done': todo.done}">{{todo.title}}</span>
  </li>
</ul>

There are two parts involved in displaying the output in the web page:

1. ng-repeat="todo in todos"
2. {{todo.title}}

The Angular ng-repeat directive will basically repeat the HTML element it is defined in for as many data elements as are found in the container that it specifies. In this case the container (usually an array) is called ‘todos’. This is like a for loop. For example:

For todo in todos, repeat this <li> element and display the title of each todo.

{{todo.title}} is what displays the value associated with the key ‘title’ in each todo object.

For more information about ng-repeat, see:
https://www.w3schools.com/angular/ng_ng-repeat.asp
https://docs.angularjs.org/api/ng/directive/ngRepeat

 

Step 7: Handle checkboxes for deleting items

In addition to outputting the title of each todo in the previous step, we can also output a checkbox with each todo which will allow that todo item to be deleted. To do this, we will use ng-model again, but this time, bind to a different key in the todo object. For example, in the HTML:

<input type="checkbox" ng-model="todo.done"/>
<span ng-class="{'done': todo.done}">{{todo.title}}</span>

This time ng-model is binding to “todo.done”, which by default is set to false. For example:

{'title': $scope.newTodo, 'done': false}

The next line, which is a span, uses ng-class which tells the CSS how to style the todo item if the checkbox is clicked. ng-class basically says “If this condition is true, then use the CSS styling associated with this CSS class. Here is the CSS for the “done” class:

.done {
  text-decoration: line-through;
  color: #ccc;
}

When a checkbox is clicked, the CSS ‘done’ class is activated due to the use of ng-class which gives a strike through style to the item. Also, because of the data binding with ng-model, the todo.done value is toggled to true.

For more information about ng-class, see:
https://docs.angularjs.org/api/ng/directive/ngClass

 

Step 8: Removing checked items

The final step is to set up a button that will remove all completed todo items that have already been checked. Unlike the ng-submit button we used earlier, this time we will use ng-click with the argument being the name of the angular function that is defined in the controller.

<button ng-click="clearCompleted()">Clear Completed</button>

The ng-click directive tells Angular to launch the clearCompleted() function when the “Clear Completed” button is clicked. The clearCompleted() function defined in the controller looks like this:

$scope.clearCompleted = function() {
    $scope.todos = $scope.todos.filter(function(item){
    return !item.done
})

Which basically means, use a filter to only return todo items that don’t have todo.done = true.

For more information about the ng-click directive, see:
https://www.w3schools.com/angular/ng_ng-click.asp
https://docs.angularjs.org/api/ng/directive/ngClick

Well, that’s it for this introduction to Angular.

Note: This To Do app does not save list state, so refreshing the page will delete everything on the list. I will write about how to save the list so that it persists in another article.