Javascript MVC tutorial: create a todo list using Stapes.js in less than 100 lines of code (part 2)
In the first part of this tutorial we wrote a really simple todo list. In this part i’ll show you how to expand it with a templating mechanism, a way to remove the todos and how to use localStorage
to save the todos between browser refreshes.
Templating
From the first part you might have noticed that i’ve added some HTML using jQuery in the controller. This is usually not how you should do things in a MVC framework. Instead of writing inline HTML you’re better of using templating.
Like with anything else in Stapes, you’re free to use any templating mechanism you want, but for now i’ll be using the popular Handlebars.js library.
We’ll start by adding the Handlebars.js library to the index.html
file and adding a small inline template using a script
tag. Add this before the first script
tag in the index.html
file:
The type="text/html"
attribute will prevent the browser from parsing this text as Javascript. We’ll now include a new listTemplate
variable to our app.js
file to parse the template. Add this to the top of app.js.
In any part of the code you can now get the HTML for this template by simply calling listTemplate
as a method.
Now, let’s use the template for our todo app! We’ll be creating a new listView
and remove the old jQuery code from our controller. Because we have two views now we’ll be renaming TodosView
to InputView
. It’s usally best to use a view for a single element, and keep it as simple as possible.
Here’s the complete code for our new app.js
Try refreshing your browser and add some todos. Notice that the number at the bottom of the list (‘todos left’) increases every time you enter a new todo.
A closer look at ListView
Let’s take a closer look a the ListView
.
The render
function takes care of rendering the todos as a block of HTML code. It uses the template
property we set on the view to get the html. The this.template
method takes one parameter: a Javascript object that contains the data it should render:
The size
method is a part of every Stapes module and returns the number of items. Let’s have a look at the part of the template:
So, whenever this template is rendered the size
property is updated with the number of todos in the TodosModel
.
The todos
property is a little more complicated. getAllAsArray
returns all items in the TodosModel
as an array, so we can iterate over the items in the template:
Note the {{text}}
property. We changed a little part of the InputView
to make sure every item in the model has a text
attribute. The {{id}}
property is automatically added to every object whenever you call getAllAsArray
. We’ll see why this is handy in a moment.
Removing todos
Adding todos is nice, but you might want to get something done as well! As you probably saw in your browser every todo now also includes a small checkbox. We’ll be adjusting the ListView
to make it possible to remove todos.
Add a bindEventHandlers
method to your ListView
, just before the render
method:
We also need to call this method, so add this to the end of the constructor
in your ListView
.
Now reload your browser, add some todos and try clicking the checkbox. Hurrah! We can finally get some stuff done ;)
A closer look at the remove function
So, how does the bindEventHandlers()
function in ListView
work? We add an event handler to all items with the class remove
(all checkboxes have this class). Whenever one of them is clicked we get the id
for the todo by looking at the parents and getting it from the data-id
attribute we set earlier in the template.
After that it’s a simple call to Stapes’ remove
function to remove the element by id.
Remembering stuff
We’ll be wrapping up this tutorial with a small addition to our model. Don’t you think it’s irritating to have an empty list every time you refresh the browser? Let’s use the new HTML5 window.localStorage
feature to remember it between browser refreshes.
Note that localStorage
is available in all recent browsers, including Internet Explorer 8. If you need to support older browsers there are plenty of alternatives to make it work on those browsers too.
So, let’s write some code. We’ll be using the JSON format to save our model into the browser’s localStorage
. Change your TodosModel
to this piece of code:
Change the init
method of the TodosController
to this:
Check it out! Add some todos, refresh your browser and voila, all your todos are saved!
A better look at the new TodosModel
The TodosModel
module now has a new constructor
that gets the todos from localStorage
, parses the JSON and uses Stapes’ set
on itself to add all the todos to the model. set
works just like push
, except that it takes key-value pairs and so it doesn’t automatically create new ids.
We use a nifty trick here: set
also accepts an object with multiple key-value pairs, like our list of todos. The todos
variable gets a Javascript object back from localStorage
that looks like this:
Note that in your browser the ids will look different because they are randomily made up whenever you add a new todo.
The save
method saves all of the todos in localStorage
by getting them from the TodosModel
using getAll
, then converting them to JSON.
We changed the event handler for the change
event in our controller to update the localStorage
whenever an event is added or removed from the model. Also note the final line of the TodosController
constructor
: we need to do an initial render
of the ListView
to show the list of todos.
Wrapping it up
You should now have a completely functional, persistent todo list in your browser. If you want to experiment feel free to use the jsFiddle i’ve setup.
If you want to learn more you could read the Stapes.js documentation and play around with the more advanced todo example.
If you have any comments or questions feel free to post them in the comments section, send me an e-mail, or send a message to @hayify on Twitter.
Thanks for reading!
Greg Baker
Nice tutorial. I have your code (via github) and have played with the todo already.
I think many would benefit from an even more simple – w/o Handlebars perhaps, example. Like a starter kit maybe. Anyway, I like your approach and will continue to poke around the edges of it. Thanks. Greg
Everardo
Greetings,
Thank you for tutorial! I wonder if you have any examples on how to model CRUD applications with Stapes.js?
Thanks,
Everardo