Recently I came across a website called todomvc.com. It is a website designed to help you select a mvc framework (mvc = model-view-controller). A mvc framework makes it easier to develop client-side web applications.
This off course piqued my interest as my opensource project Reken's main design goal is to do exactly that. The todomvc uses a reference web UI to compare the different implementations. They provide a fully styled html Todo application, but it is not functional. The functionality is supposed to be provided by a framework.
And the Todo application has quite some functionality. A user should be able to created, edit, delete and mark a todo item completed. It should also list all the todos, or filter just the uncompleted ones (with a counter) or the completed ones. The latter with an option to delete all completed todos. The UI should also dynamically adapt if there are no todo's at all, or the delete completed todos button should be disabled if there aren't any. The UI should also persist its state (todos / active filter) and when the user revisits the app should reinstate the todos and filter. The filters should also be reflected by the url ie it needs to be routed.
On the todomvc website you can find a number of implementations from the various frameworks such as React, Vue, Backbone, Ember, Backbone, Knockout and many others. Did not know there were that many frameworks. There also a few vanilla js and a Jquery implementations.
Naturally my fingers itched to get me hands dirty with a Reken implementation. And within an hour had most of it working. There were a couple usecases I had not covered with Reken yet:
- Multiple data-driven classes per element
- The ability to bind a variable to an input and also register a change event
- Data-driven focus management
All of these usecases made sense and therefor added them to Reken. With that I was able to complete all the required functionality. When I was ready to issue a pull request for the Reken implementation on their repo, I was disappointed. It turned out there were requirements before you were allowed to submit a pull request. The major blocker was needing more than 5,000 github stars. :-( Nowhere close to that.
Anyway was still pretty pleased with the implementation. Here a link with the Reken based TodoMVC application hosted.
I'll now go through the different parts of the UI and explain how it is implemented with Reken.
First the header and in the input control to enter new todos
data-value attribute binds the input control to the
data-on-change attribute has the code to excute when the value changes. It adds the new todo to the
state.tasks array. It also saves the state across sessions with
data-calc attribute we set the focus on the input control if no other item is being edited and if it not already has focus.
Next the list of todos. There is a lot going on here. First a checkbox to mark tasks finished. Then the label for the task. When the label is double-clicked it brings up the input control to edit the label. When hovering a task a delete icon appears to delete the task.
data-for attribute loops over the list of tasks. Depending on the value of currentFilter all task, unfinished tasks and finished tasks. For each item it populates the
data-class attribute sets the
editing class when the current task is being edited. It also set the
completed class when the task is completed.
input checkbox attribute
ata-value binds the checkbox to task property
data-on-change attribute makes sure the state gets saved.
data-on-dblclick gets the task in edit mode by seting the
editTask variable to the task index. With the
data-text attribute we set the task title on the label.
data-actionattribute deletes the task when clicked.
input text attribute
data-value we are editing the task's title
data-calc attribute ensure the focus is on the input control and the cursor is at the end of the input. Both the
data-on-change and the
data-on-focusout ensure the task is updated and the state is saved.
The footer component shows the number of uncompleted task. The 3 different filters All, Active and Completed will filter the task list. The Clear completed delete all completed tasks.
data-if only shows the toolbar when there are tasks. The
data-html attribute displays the number of open tasks.
li a attribute
data-class sets the
selected class on the element to show which filter is active.
And last the
data-if only shows this button when there are completed tasks. The
data-action attribute deletes the completed tasks and saves the state.
That was basically the application. Oh and one more thing there is a
data-route attribute on the
body element with the route
This changes the
currentFilter variable based on the hash of the url as set by the filter links.