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
Todomodel that connects to a dummy data store (just an array). ThefindAll,findOne,updateanddestroymethods simply returning the required deferreds.It then creates a
Todoscontrol that manages a list oftodos. When a new Todos control is created on an element vianew Todos("#todos")it uses theTodomodel to findAll todo instances, renders them withtodosEJSand inserts them into theTodoscontrol instance's element.The template
todosEJSiterates through each todo instance usinglist. For each todo, it creates an<li>element. It adds the instance's data to the<li>element's$.datawith:<%= (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'scheckedattribute, the span's class attribute, and the span's content.Todosalso 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 theRoutingcontrol."li .complete click"gets the todo instance clicked from$.dataand 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$.dataand destroys it. When an instance in a list is destroyed, it is automatically removed from the list. EJS'slistmethod listens for these changes and automatically updates the DOM.Next, an
Editorcontrol constructor is created. Editor is designed to take a todo instance and edit it's name property. First a newEditoris 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
Routingcontrol constructor is created that manages the interaction between anEditorandTodoscontrol.Routingis a traditional controller, whileEditorandTodosare traditional views. When a newRoutingis created, it creates anEditorandTodoscontrol. 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.Routingalso listens to an"li selected"event. This is the event created by theTodoscontrol. When this event happens,Routingupdates 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.Observecancan.computeto organize client state and pass it to child controls.How it works