Todo App using Web API and Knockout

In this post I am going to show you how to develop a todo app using knockoutjs and microsoft Web API.

What is knockoutjs

”Knockout is a standalone JavaScript implementation of the Model-View-ViewModel pattern with templates. The underlying principles are therefore: a clear separation between domain data, view components and data to be displayed.”-Wikipedia

Knockout is built around three core features:

  1. Observables and dependency tracking
  2. Declarative bindings
  3. Templating

Before diving to example code first go through the following http://knockoutjs.com/documentation/observables.html#mvvm_and_view_models

Open visual studio and create a new Web API application

image

Open Package Manager console and install knockoutjs as shown in below image

image

Right click the Model folder and add a new class named TodoItem and paste following code.

 public class TodoItem
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public bool Done { get; set; }
    }

Right click the model folder again and add a new Interface class and paste following code

 public interface ITodoRepository
    {
        IEnumerable<TodoItem> GetAll();
        void AddTodo(TodoItem item);
    }
}

Add a new class inside model folder and paste following code inside it

 public class TodRepository : ITodoRepository
    {
        private static List<TodoItem> _localTodos;
        private int MaxId()
        {
            return _localTodos.Max(x => x.Id) + 1;
        }
        public TodRepository()
        {
            _localTodos = new List<TodoItem>() {
                    new TodoItem{Id=1,Title="Todo Item 1",Done=false},
                    new TodoItem{Id=2,Title="Todo Item 2",Done=false},
                    new TodoItem{Id=3,Title="Todo Item 3",Done=true},
                };

        }


        public IEnumerable<TodoItem> GetAll()
        {
            return _localTodos;
        }

        public void AddTodo(TodoItem item)
        {
           
            var id = MaxId();
            TodoItem newTodo = new TodoItem() { Id = id, Title = item.Title, Done = item.Done };
            _localTodos.Add(newTodo);
        }

        public void Delete(int id)
        {
            var taskToDeleted = _localTodos.Find(x => x.Id == id);
            _localTodos.Remove(taskToDeleted);
        }

    }

Go to controller folder and rename the ValuesController to TodoController and paste the following code.

 public class TodoController : ApiController
    {
        // GET api/values
        private ITodoRepository _repo;
        public TodoController()
        {
            _repo = new TodRepository();
        }
        public IEnumerable<TodoItem> Get()
        {
            return _repo.GetAll();
        }

        public void Post([FromBody]TodoItem value)
        {
            _repo.AddTodo(value);
        }

    }

Till now I have not done nothing related to knockoutjs.Let’s start the second part

Opend Index.cshtml and remove everything from it and paste following markup

<h1>Todo App</h1>
<div class="row">

    <form role="form">
        <div class="form-group">
            <label for="email">Title:</label>
            <input type="text" class="form-control" data-bind="value: taskName" id=" txttitle" placeholder="Enter Title">
        </div>

        <button type="submit" data-bind="click:addTask" class="btn btn-default">Submit</button>
    </form>
    <hr />
    <div class="col-md-6">
        <table class="table">
            <thead>
                <tr>
                    <th>Title</th>
                    <th>Completed?</th>
                </tr>
            </thead>
            <tbody data-bind="foreach:todos">
                <tr>
                    <td data-bind="text:Title"></td>
                    <td><input type="checkbox" data-bind="checked:Done" /> </td>
                    <td>
                        <a href="#" title="Delete the task" data-bind="click:$parent.deleteTodo" class="glyphicon glyphicon-trash"></a>
                    </td>


                </tr>
            </tbody>
        </table>
    </div>
</div>


 

The basic layout of the html is simple, and taken from the inspiring example applications. The noteworthy parts are the data-bind attributes that are sprinkled in the appropriate places:

There is a input textbox which has the same value as the viewModels taskName and there is button which will fire addTask function on viewmodel.

Right click the project and add new javascript file inside scripts folder named todoApp.js and add following code

function TodoItem(Id, Title, Done) {
    var self = this;
    self.Id = Id;
    self.Title = ko.observable(Title);
    self.Done = ko.observable(Done);
    self.Done.subscribe(function () {


    });
}
function TodoViewModel() {

    var self = this;
    self.todos = ko.observableArray([]);
    self.taskName = ko.observable();

    self.addTask = function () {
        var todoItem = new TodoItem(0, self.taskName(), false);
        self.todos.push(todoItem);
        $.ajax({
            type: "POST",
            url: "/api/todo",
            data: ko.toJSON(todoItem),
            dataType: "json",
            contentType: "application/json",
            success: function (data) {

            }

        });

    };
    self.deleteTodo = function (data) {
        self.todos.remove(data);
        $.ajax({
            type: "DELETE",
            url: "/api/todo/" + data.Id,
            dataType: "json",
            contentType: "application/json",
            success: function () {
               
            }

        });
    };
    self.init = function () {
        $.getJSON("/api/todo", function (data) {
            $.each(data, function (index, item) {
                self.todos.push(new TodoItem(item.Id, item.Title, item.Done));
            });
        });
    };

}
$(document).ready(function () {

    var viewModel = new TodoViewModel();
    viewModel.init();
    ko.applyBindings(viewModel);
});

open _Layout.cshtml and add following script

    <script src="~/Scripts/knockout-3.2.0.js"></script>
    <script src="~/Scripts/todoApp.js"></script>

No comments:

Post a Comment