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.