ToDo list using AngularJS and Firebase

by Sajeetharan Sinnathurai

HTML

<script src="https://cdn.firebase.com/js/client/2.2.2/firebase.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular.min.js"></script>
<script src="https://cdn.firebase.com/libs/angularfire/1.0.0/angularfire.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.15/angular-animate.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<div ng-controller="TodoCtrl" class="container" ng-app="TodoApp">

<h2>ToDo list using AngularJS and Firebase</h2>
<h4>See real time binding by opening two browsers and adding, updating, or removing a TODO</h4>


<!--ADD ITEM FORM-->
<form name="todoForm">

    <div>
        <input type="text"
               name="todoNameField"
               ng-model="todoName"
               placeholder="Add new task (min 3 chars)"
               required ng-minlength="3"
               class="form-control"
               ng-keyup="($event.keyCode == 13 && todoName.length > 2) ? addItem() : return"
               style="margin-bottom: 10px"
                />

        <button ng-click="addTodo()"
                ng-hide="myForm.todoNameField.$invalid"
                class="btn btn-primary" type="button"
                >Save Todo
        </button>
    </div>

</form>

    <hr />

<!--TODO LIST-->

<h4 ng-show="(todos | filter:{status: 'pending'}).length">Pending</h4>

<div ng-repeat="todo in todos | filter:{status: 'pending'}"
     class="row list-item">

    <div class="col-md-6">

        <!--TODO LABEL-->
        <span>{{todo.name}}</span>
    </div>
    <div class="col-md-6 text-right">
        <!--START TODO BUTTON-->
        <a class="btn btn-warning"
           ng-click="startTodo($index, todo)">
            Start
        </a>

        <!--DELETE TODO BUTTON-->
        <a class="btn btn-danger"
           ng-click="removeTodo($index, todo)">
            <i class="glyphicon glyphicon-remove"></i> Remove
       ...

CSS

.list-item {
    padding: 10px 0;
    border: 1px solid #ccc;
}

JavaScript

var todoApp = angular.module('TodoApp', ['firebase']);


todoApp.controller('TodoCtrl', ['$scope', '$firebaseArray',
    function($scope, $firebaseArray) {
        
    // CREATE A FIREBASE REFERENCE
    var todosRef = new Firebase('https://teamtododemo.firebaseio.com/');

    // GET TODOS AS AN ARRAY
    $scope.todos = $firebaseArray(todosRef);

    // ADD TODO ITEM METHOD
    $scope.addTodo = function () {

        // CREATE A UNIQUE ID
        var timestamp = new Date().valueOf();

        $scope.todos.$add({
            id: timestamp,
            name: $scope.todoName,
            status: 'pending'
        });

        $scope.todoName = "";

    };

    // REMOVE TODO ITEM METHOD
    $scope.removeTodo = function (index, todo) {
        
        // CHECK THAT ITEM IS VALID
        if (todo.id === undefined)return;

        // FIREBASE: REMOVE ITEM FROM LIST
        $scope.todos.$remove(todo);

    };

    // MARK TODO AS IN PROGRESS METHOD
    $scope.startTodo = function (index, todo) {

        // CHECK THAT ITEM IS VALID
        if (todo.id === undefined)return;

        // UPDATE STATUS TO IN PROGRESS AND SAVE
        todo.status = 'in progress';
        $scope.todos.$save(todo);

    };

    // MARK TODO AS COMPLETE METHOD
    $scope.completeTodo = function (index, todo) {

        // CHECK THAT ITEM IS VALID
        if (todo.id === undefined)return;

        // UPDATE STATUS TO COMPLETE AND SAVE
        todo.status = 'complete';
        $scope.todos.$save(todo);
    };

}]);