The following recipes show a bunch of functionality working together.
Basic Todo
This recipe demonstrates the very basic todo app covered in the tutorial. You
can select a todo and edit it's text. You can also delete a todo. The app is
also history enabled, letting you move forward and back through different todos.
How it works
The app starts by creating a Todo model that connects to a dummy data
store (just an array). The findAll, findOne, update and destroy methods
simply returning the required deferreds.
It then creates a Todos control that manages a list of todos. When a new Todos control is created
on an element via new Todos("#todos") it uses the Todo model to findAll todo instances,
renders them with todosEJS and inserts them into the Todos control instance's element.
The template todosEJS iterates through each todo instance using list. For each todo,
it creates an <li> element. It adds the instance's data to the <li> element's $.data
with: <%= (el) -> el.data('todo',todo) %>. Within each <li> it creates a
checkbox, span to contain the name, and destroy link. EJS's live-binding will be used to
update the checkbox's checked attribute, the span's class attribute, and the span's content.
Todos also binds on various events such as "li click", "li .complete click", and
"li .destroy click". Here's what they do:
"li click" triggers a synthetic selected event on the li clicked
with the model data. This is a great technique for making reusable event-based widgets. This
selected event is listened to by the Routing control.
"li .complete click" gets the todo instance clicked from $.data and updates
it's complete property. EJSs live-binding will take care of updating the DOM for you.
"li .destroy click" gets the todo instance from $.data and destroys it. When an instance
in a list is destroyed, it is automatically removed from the list. EJS's list method
listens for these changes and automatically updates the DOM.
Next, an Editor control constructor is created. Editor is designed to take a todo instance and
edit it's name property. First a new Editor is created on an element like:
var editor = new Editor("#editor")
And an instance to edit is passed like:
editor.todo( todo );
When editor.todo( todo ) is called, it updates the editor's todo option and calls this.on(). This rebinds
the editor's event handlers like "{todo} updated" and "{todo} destroyed" to bind to the
updated todo option. Then it calls this.setName() which updates the
editor element's value.
"{todo} updated" listens when a todo has been updated on the server and updates the name.
"{todo} destroyed" hides the editor if it's todo has been destroyed.
"change" listens to the input element's value changing, updates the todo's name attribute and saves
it to to the server.
Finally a Routing control constructor is created that manages the interaction between an Editor and
Todos control. Routing is a traditional controller, while Editor and Todos are traditional
views. When a new Routing is created, it creates an Editor and Todos control. It also
listens to changes in routes with "route" and "todos/:id route".
"route" matches when the hash is empty and hides the editor.
"todos/:id route" matches when the route is like #!todos/5. When this happens, it shows the
editor, loads that Todo with the model, and passed it to the editor.
Routing also listens to an "li selected" event. This is the event created by
the Todos control. When this event happens, Routing updates the hash with the select todo's id.
Paginated Grid with Buttons
Paginate through a list of links. This recipe shows how to use can.Observe can can.compute to
organize client state and pass it to child controls.
The following recipes show a bunch of functionality working together.
Basic Todo
This recipe demonstrates the very basic todo app covered in the tutorial. You can select a todo and edit it's text. You can also delete a todo. The app is also history enabled, letting you move forward and back through different todos.
How it works
The app starts by creating a
Todo
model that connects to a dummy data store (just an array). ThefindAll
,findOne
,update
anddestroy
methods simply returning the required deferreds.It then creates a
Todos
control that manages a list oftodos
. When a new Todos control is created on an element vianew Todos("#todos")
it uses theTodo
model to findAll todo instances, renders them withtodosEJS
and inserts them into theTodos
control instance's element.The template
todosEJS
iterates through each todo instance usinglist
. For each todo, it creates an<li>
element. It adds the instance's data to the<li>
element's$.data
with:<%= (el) -> el.data('todo',todo) %>
. Within each<li>
it creates a checkbox, span to contain the name, and destroy link. EJS's live-binding will be used to update the checkbox'schecked
attribute, the span's class attribute, and the span's content.Todos
also binds on various events such as"li click"
,"li .complete click"
, and"li .destroy click"
. Here's what they do:"li click"
triggers a synthetic selected event on the li clicked with the model data. This is a great technique for making reusable event-based widgets. This selected event is listened to by theRouting
control."li .complete click"
gets the todo instance clicked from$.data
and updates it's complete property. EJSs live-binding will take care of updating the DOM for you."li .destroy click"
gets the todo instance from$.data
and destroys it. When an instance in a list is destroyed, it is automatically removed from the list. EJS'slist
method listens for these changes and automatically updates the DOM.Next, an
Editor
control constructor is created. Editor is designed to take a todo instance and edit it's name property. First a newEditor
is created on an element like:And an instance to edit is passed like:
When
editor.todo( todo )
is called, it updates the editor's todo option and callsthis.on()
. This rebinds the editor's event handlers like"{todo} updated"
and"{todo} destroyed"
to bind to the updated todo option. Then it callsthis.setName()
which updates the editor element's value."{todo} updated"
listens when a todo has been updated on the server and updates the name."{todo} destroyed"
hides the editor if it's todo has been destroyed."change"
listens to the input element's value changing, updates the todo's name attribute and saves it to to the server.Finally a
Routing
control constructor is created that manages the interaction between anEditor
andTodos
control.Routing
is a traditional controller, whileEditor
andTodos
are traditional views. When a newRouting
is created, it creates anEditor
andTodos
control. It also listens to changes in routes with"route"
and"todos/:id route"
."route"
matches when the hash is empty and hides the editor."todos/:id route"
matches when the route is like#!todos/5
. When this happens, it shows the editor, loads that Todo with the model, and passed it to the editor.Routing
also listens to an"li selected"
event. This is the event created by theTodos
control. When this event happens,Routing
updates the hash with the select todo's id.Paginated Grid with Buttons
Paginate through a list of links. This recipe shows how to use
can.Observe
cancan.compute
to organize client state and pass it to child controls.How it works