Todo App using Web API and Knockout

In this post, I am going to show you how to develop a to-do 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 into 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 the below image
image
Right-click the Model folder and add a new class named TodoItem and paste the 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 the following code

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

Add a new class inside the model folder and paste the 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 the 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 anything related to knockoutjs. Let’s start the second part
Open Index.cshtml and remove everything from it and paste the 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 an input textbox that has the same value as the view models taskName and there is a button that will fire the addTask function on ViewModel.
Right-click the project and add a new javascript file inside the scripts folder named todoApp.js and add the 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 the following script

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

Please do not post any spam link in the comment box😊

إرسال تعليق (0)
أحدث أقدم