Todo Application

There are 10 spirals in the [todo_mvc_spirals] (https://github.com/dzenanr/todo_mvc_spirals) project: from todo_mvc_s00 to todo_mvc_s09. The final version is the [dartling_todos] (https://github.com/dzenanr/dartling_todos) application. This post is about todo_mvc_s01.

In the todo_mvc_s01 spiral (Figure 1),

![Alt Figure 1: todo_mvc_s01] (/img/todo_mvc_s01/todo_mvc_s01.png)

Figure 1: todo_mvc_s01.

there is a new lib/app folder. In the todo_app.dart file, the TodoApp class (Code 1)

Code 1: TodoApp class properties.

class TodoApp {
  Tasks tasks;
  var todoWidgets = new List<TodoWidget>();
  Element todoListElement = query('#todo-list');
  
}

has 3 properties: tasks, todoWidgets and todoListElement. The Tasks class is generated by dartling in the lib/todo/mvc folder. The TodoWidget class is defined in the lib/app/todo_widget.dart file. The todo-list id is used in the web/todo_mvc.html file (Code 2) to get access to the corresponding DOM element.

Code 2: html5 section.

<section id="todoapp">
    <header id="header">
      <h1>todos</h1>
      <input id="new-todo" placeholder="What needs to be done?" autofocus>
    </header>
    <section id="main">
      <ul id="todo-list"></ul>
    </section>
  </section>

At the beginning of the constructor of the TodoApp class (Code 3), the dartling repository is used to get the todo domain. There is only one model in the domain, and only one entry into the model, which is an empty collection of tasks.

Code 3: TodoApp class constructor.

TodoApp(repo) {
    var todo = repo.getDomainModels(TodoRepo.todoDomainCode);
    var mvc = todo.getModelEntries(TodoRepo.todoMvcModelCode);
    tasks = mvc.getEntry('Task');
    
    InputElement newTodoElement = query('#new-todo');
    newTodoElement.on.keyPress.add((KeyboardEvent e) {
      if (e.keyCode == KeyCode.ENTER) {
        var title = newTodoElement.value.trim();
        if (title != '') {
          var task = new Task(tasks.concept);
          task.title = title;
          addTodo(task);
          newTodoElement.value = '';
        }
      }
    });
  }

The application is created in the main function of the web/todo_mvc.dart file (Code 4).

Code 4: main function.

main() {
  new TodoApp(new TodoRepo());
}

A new todo is entered by a user into the input element (Figure 2).

![Alt Figure 2: todo] (/img/todo_mvc_s01/todo.png)

Figure 2: todo.

The entered value becomes the title of a newly created task, which is then added to tasks by the addTodo method (Code 5).

Code 5: addTodo method.

addTodo(Task task) {
    tasks.add(task);
    var todoWidget = new TodoWidget(task);
    todoWidgets.add(todoWidget);
    todoListElement.nodes.add(todoWidget.createElement());
  }

A todo widget is constructed based on the task (Code 6) and it is added to the list of todo widgets. A new DOM node is created by the createElement method (Code 6) and added to the todo list element. The todo widget may be toggled to the completed state.

Code 6: TodoWidget class.

class TodoWidget {
  Task task;
  Element element;
  Element toggleElement;

  TodoWidget(this.task);

  Element createElement() {
    element = new Element.html('''
	<li ${task.completed ? 'class="completed"' : ''}>
	  <div class='view'>
          <input class='toggle' type='checkbox' 
            ${task.completed ? 'checked' : ''}>
	    <label class='todo-content'>${task.title}</label>
	  </div>
	</li>
    ''');

    toggleElement = element.query('.toggle');
    toggleElement.on.click.add((MouseEvent e) {
      toggle();
    });

    return element;
  }

  void toggle() {
    task.completed = !task.completed;
    toggleElement.checked = task.completed;
    if (task.completed) {
      element.classes.add('completed');
    } else {
      element.classes.remove('completed');
    }
  }

}

I have taken the web/css/base.css file as it is. The completed css class is shown in Code 7.

Code 7: completed css class.

#todo-list li.completed label {
  color: #a9a9a9;
  text-decoration: line-through;
}
blog comments powered by Disqus