The rest of this blog post describes the GWT implementation.
The GWT Todo application
My implementation of the Todo application is nothing notable, just MVP-by-numbers as illustrated by the UML class diagram below:
Very briefly ... the
ToDoPresenter manages a collection of
ToDoItem instances, this includes create, update, delete and persistence. The presenter exposes two interfaces, ToDoPresenter.View, which is the interface that a view is expected to implement, and ToDoPresenter.ViewEventHandler, which is an interface that handles view 'events'. Each
ToDoItem instance has a reference back to the presenter so that it can remove itself and notify the presenter of state changes (yes, I wish Java had events and
The view is implemented declaratively via the GWT UiBinder. The markup for the view is shown below:
This closely mirrors the standard TodoMVC template.
Todo Item Rendering
The most interesting part of the application is the way that the list of Todo items is rendered. GWT has a number of framework features that support the management of lists of data, and for this application I opted to use a Cell Widget, which is a common set of interfaces that expose and render list like data, automatically updating the UI as data is added / removed.
In the TodoMVC application the data is presented as an
AbstractDataProvider which is coupled to a
CellList view component. Unfortunately, this is where I started to hit a few problems. The TodoMVC project supplies a standard template that all implementations should follow. Within the template the list of Todo items are rendered as an unordered list (
li). However, the GWT
CellList uses a
div as the root container for list items. Furthermore, each rendered list item is also wrapped in a
div. There is no obvious way to change this functionality without re-creating the entire
CellList widget and unfortunately the target HTML output could not be achieved. As a result of this, I had to modify quite a bit of the application styling to target the different structure.
The GWT Cell Widgets have a number of standard cell types, including checkbox cells, text input cells etc ... however, this application required quite a specialised cell, including both a checkbox and a text field, plus an edit mode which replaces the contents with an input field. To support this I implemented a
ToDoCell, which is a cell specifically designed for rendering
This cell contains two different templates, one for edit mode, the other for read-only mode:
With the render method picking one or the other template based on whether the current cell is being edited:
NOTE: The cell widget framework only creates a single instance of each cell, one for each column (for table widgets). Hence the row context information, in this case the
ToDoItem, is passed in to all methods that require the row state.
The bulk of the code within this cell implementation sits within the
onBrowserEvent method. DOM events are passed to this method, together with the cell's parent element and item being rendered. This allows you to handle keyboard, mouse and other interactions, swapping between edit and view mode etc ...
Within this method we manage the edit process, with
endEdit switching between the two different cell templates:
As a result, even though the markup differs slightly from the template, the desired functionality is the same.
I think the GWT implementation of the TodoMVC application stands up very well in comparison to the other frameworks presented there. Although, compromises in the output markup did have to be made. I think this is a reflection of the different approach that a typical GWT application development would take, where the application is designed at a higher level, in terms of panels and widgets, rather than at the markup / detail level.
Despite this, the GWT developer does have full access to the DOM, and as a result, I was able to precisely match the functionality required with little effort, even though the GWT framework itself does not support such a specialised cell type as the one required.
Hopefully other people will find this to be a useful addition to TodoMVC project!
Regards, Colin E.