To-Do List App with AngularJS

Being overwhelmed with work whether it is assignments for Uni or freelance projects, or as for the last couple of months – both, I’ve always found using “To-do” lists really helpful.
I found that using To do lists, apart from just reminding myself what I have to do, also help with:

  • Focusing
  • Adding momentum and sense of accomplishment when completing tasks
  • Keeping sense of priorities

There is also a study by a Soviet psychologist Bluma Zeigarnik which states that people tend to remember uncompleted or interrupted tasks better than completed tasks. Using a “To do” list will stimulate you to think about the uncompleted tasks you have set and unconsciously challenge you until you complete them. More information on the Zeigarnik effect here

But since I was in a Computing course (Bachelor of Science graduate with Honours at the moment), it made sense to look for a better than a “pen and paper” solution. So back in January 2017, that thought provoked me to think about building a simple web app that would do the job of keeping my “To-do” lists and allow me to tick them off. Building the solution had to utilize my web technologies skills (HTML/CSS/JavaScript) and extend my understanding of the available frameworks and libraries. I started to look for ways to build an app that would dynamically change the and update the DOM based on user action (i.e. add tasks in a list based on an input). That is how I came across AngularJS, which is a JavaScript-based framework that extends the HTML vocabulary and provides the toolset for building single-page applications.

The beauty of AngularJS is in the data binding. The framework automatically synchronises the data between the view and the model (Two-way data binding on the picture below) which allows the view to be single point of information for the template.

Traditionally, when one-way data binding is used, the template and the model are combined in the view. In that way, all of the changes the user does are not reflected, unless you write a script that constantly synchronizes them, which is not the best (or at least the easiest) approach.

The web app I ended up building had a simple structure utilizing AngularJS, which allowed me to add tasks which result in dynamically created < li > elements achieved with JavaScript.
The Angular modules that were really handy were the following:
ng-controller – managing the app behavior inside a declared element
ng-click – directly declaring a method to call, instead of registering event-handlers
ng-repeat – dynamically adding elements to the DOM when new objects are added
ng-model – linking the to do form to the model
ng-submit – accepting to do submissions

For the styling, I have used some Bootstrap elements, custom CSS, Font-Awesome and Google Fonts.

Here is a demo: To-do List App

Here is how the web app looks like:

And that is how I used “To-dos” before:

Here is the source code:

<!DOCTYPE html>
<html ng-app="todoApp">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <!-- JavaScript -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
    <script src="js/to-do.js"></script>
    <!-- Google fonts -->
    <link href="https://fonts.googleapis.com/css?family=Indie+Flower" rel="stylesheet">
    <!-- Bootstrap - Latest compiled and minified CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    <!-- Font Awesome -->
    <link rel="stylesheet" href="css/font-awesome-4.7.0/css/font-awesome.min.css">
    <!-- My styles CSS -->
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div class="wrapper" ng-controller="TodoListController as todoList">

      <div class="wrapper2">
        <div class="head">  
          <span id="jsn" class="fa fa-thumb-tack fa-2x"></span>
          <span>{{todoList.remaining()}} of {{todoList.todos.length}} Remaining</span>
        </div>  
        <a class="btn btn-primary btn-xs" href="" ng-click="todoList.clear()" role="button">Clear completed tasks</a> 
        <h2>To do List</h2>
        <br> 
        <ul class="unstyled">
          <li ng-repeat="todo in todoList.todos">
            <label class="checkbox">
              <input class="check" type="checkbox" ng-model="todo.done">
              <span class="done-{{todo.done}}">{{todo.text}}</span>
            </label>
          </li>
        </ul>

        <form ng-submit="todoList.addTodo()">
          <input class="form-control" type="text" ng-model="todoList.todoText" ng-minlenght="1" required size="10" placeholder="Add new task here">
          <input class="btn btn-primary btn-sm" type="submit" value="Add task">
        </form>
      </div>
      <br>
    </div>
  </body>
</html>
html{
  height: 100%;
}

body{
 background-color: rgb(44,62,80);
  background-image: url("img/bg-jsn.jpg");
  background-position: center;
  font-family: 'Indie Flower', cursive;
  font-size: 18px;
}

h2{
  font-family: 'Indie Flower', cursive;
  text-align: center;
  color: #286090;  
}

.wrapper{
  background-image: url("img/notebook.jpg");
  background-color: white;
  position: absolute;
  left: 0;
  right: 30%;
  top: 50px;
  padding: 20px;
  margin: auto;
  width: 420px;
  border-top-right-radius: 2%;
  border-bottom-right-radius: 2%;
}

.wrapper2{
  padding-top: 10px;
  padding-left: 50px;
}

.form-control{
  width: 100%;
  font-size: 14px;
}

.fa.fa-thumb-tack.fa-2x{
  color : #337ab7;
}

.btn.btn-primary.btn-sm{
  margin-top: 5px;
  width: 100%;
  background-color: transparent;
  color: #286090;  
  font-size: 14px;
 } 

.btn.btn-warning.btn-xs{
  background-color: #337ab7;
  border-color:#337ab7;
}

.done-true{
  text-decoration: line-through;
  color: grey;
}

.unstyled , .ng-binding, .check{
    color: #286090; 
}
angular.module('todoApp', [])
  .controller('TodoListController', function() {
    //var to hold the list of todos
    var todoList = this;
    todoList.todos = [];
    
    //adding new todo items
    todoList.addTodo = function() {
      todoList.todos.push({text:todoList.todoText, done:false});

      //clear the form after adding adding a new todo
      todoList.todoText = '';
    };
 
    //function to count the items that remain to be completed 
    todoList.remaining = function() {
      var count = 0;
      angular.forEach(todoList.todos, function(todo) {
        count += todo.done ? 0 : 1;
      });
      return count;
    };
    
    //function to clear the completed todos
    todoList.clear = function() {
      var oldTodos = todoList.todos;
      todoList.todos = [];
      angular.forEach(oldTodos, function(todo) {
        if (!todo.done) todoList.todos.push(todo);
      });
    };
  });

Helpful sources:

Zeigarnik effect
Single Page Applications – Intro
AngularJS
Bootstrap
Font Awesome
Google Font API

Share this Post

Leave a Reply

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