TodoMVC with Silk and snippets
This page walks through the TodoMVC variant written with Silk and snippets. It shows the same model as TodoMVC with Silk, and most of its view is the same. The two variants differ in how a todo gets its markup. Here the markup comes from the page, as a snippet, and the view builds nothing of it. This page shows only what differs. It builds on Snippets, markup from the page too.
The page
silk-snippets.html is silk.html with its own title, its own bundle, and its own class to start, SilkSnippetsTodoApp. Its list holds the item of the template, as a snippet, with the label as its caret:
<ul class="todo-list">
<li data-snippet="todo">
<div class="view">
<input class="toggle" type="checkbox">
<label data-snippet-caret></label>
<button class="destroy"></button>
</div>
<input class="edit">
</li>
</ul>
Domite takes the item off the page when Amber starts, and keeps it under the name todo.
The view
The view is the package TodoMVC-Silk-Snippets, with one class, SilkSnippetsTodoApp. It keeps the todos under todos-amber-silk-snippets. It attaches, binds, routes and renders with the methods of SilkTodoApp, all but renderTodo:. It has no class for one todo. Instead, renderTodo: puts a copy of the snippet and binds it:
renderTodo: aTodo
| label item |
label := listElement todo: aTodo title.
item := Silk fromElement: label frame.
item domClass: 'completed' be: aTodo isCompleted.
(item at: '.toggle')
propAt: 'checked' put: aTodo isCompleted;
on: #change bind: [
todoList toggle: aTodo.
self render ].
label on: #dblclick bind: [ self startEditing: aTodo in: item ].
(item at: '.destroy') on: #click bind: [
todoList remove: aTodo.
self render ]
listElement todo: aTodo title puts a copy into the list, with the title in the label. The message answers a Silk on the label, and the whole item is the frame of that Silk. item at: then finds the checkbox and the button in the copy. The copy is in the list before the view sets its state. So the class goes by domClass:be:, and the checkbox by propAt:put:. The bindings do what those of SilkTodoItem do. Here the view changes the list itself, since no item object stands between.
Editing
The edit belongs to the view too. startEditing:in: takes the todo and its item:
startEditing: aTodo in: anItem
| edit |
edit := anItem at: '.edit'.
anItem addDomClass: 'editing'.
edit propAt: 'value' put: aTodo title.
self bindEdit: edit of: aTodo.
edit asDomNode focus
bindEdit:of: binds Enter, Escape and blur as SilkTodoItem >> bindEdit: does. It takes the blur handler off the same way. A save goes to finishEditing:with::
finishEditing: aTodo with: aString
todoList retitle: aTodo to: aString.
self render
What each point costs
Five points of the table in TodoMVC with Silk are somewhere else here. The rest are where that table puts them, in SilkSnippetsTodoApp:
| The specification says | Where it is | What it takes |
|---|---|---|
Toggle, class completed |
renderTodo: |
one binding, one domClass:be: |
| Destroy button on hover | renderTodo: |
one binding; the stylesheet shows the button |
| Double-click edits | renderTodo:, startEditing:in: |
one binding, one method |
| Enter or blur saves, Escape cancels, empty destroys | bindEdit:of:, finishEditing:with:, TodoList >> retitle:to: |
two bindings; the model removes the todo |
Persistence under todos-amber-silk-snippets |
start, TodoStore |
one key; the model saves |
The snippet takes the place of the tag messages. listElement todo: puts the whole item, and frame reaches it from the label. The same three things as in the Silk variant reach past Silk to the DOM.
The tests of the view
SilkSnippetsTodoAppTest, in TodoMVC-Silk-Snippets-Tests, answers attach:to: as SilkTodoAppTest does. It answers one message more, todoListMarkup, with the snippet of the page. TodoAppTest puts that markup into the list of its fixture. Then it gives the snippets of the fixture to Domite, before the view attaches. The 25 tests are the same for both variants.
Running it
Open http://localhost:4000/silk-snippets.html, and try it as TodoMVC with Silk says. The todos are in localStorage under todos-amber-silk-snippets. The test runner of Helios runs the 25 tests of SilkSnippetsTodoAppTest on the page.