This tutorial will teach you how to put together a Todo app using CoffeeScript and BackboneJS. You can find the entire code for this tutorial on the Github repository.
Here’s What We’ll Build
The todo app is inspired by TodoMVC, except that we’re using Backbone.js alongside CoffeeScript as our stack, and we’ll style the app differently.
It should allow a user to specify items to be done later, and to check off those items as they complete them. In addition, a user can filter items by status so they can see just the completed items or the non-completed ones. Here’s another screenshot of the application.
Funny story about CoffeeScript and BackboneJS, they have something in common.
Getting Backbone.js And Coffeescript
First order of business, download Backbone.js here. You’ll want to follow the instructions as far as downloading Backbone’s dependencies as well, which should be just Underscore and jQuery. This tutorial is based on version 1.3.3 of Backbone.js, but should work with newer versions. Given the stability of Backbone, even older versions of the library will work with this example code with minimal modifications. Another great benefit of working with Backbone.
For CoffeeScript, the recommended way is to install the command line compiler and REPL via npm. Install it using the installation instructions found here.
Next, inside your js directory, create a new directory called lib where you will place all of Backbone.js and its dependencies, excluding CoffeeScript which has its own usage and installation as detailed above.
Assuming you have CoffeeScript, Backbone.js and dependencies installed, there remains one more dependency. If you scan my source code, you’ll see I’m using the Backbone.LocalStorage plugin to store the Todos. You should grab a copy of this file and save it, again, in your lib folder.
So currently, your folder structure should look as follows
Note, there is nothing special about the “lib” folder, it’s just an arbitrary name for a folder where we are holding our application’s libraries.
Say Hello World
Now let’s create our home page. Create a new file inside your BackboneTodos directory, which is the root folder of the app. Call the new file, predictably, index.html
Inside index.html, let’s create the basic HTML template that says “Hello World” so we know we’re in business. Here’s the code you should put in index.html
You’ll notice that I’m including some shims and meta tags. Copy everything in. This is just a standard boilerplate that sets up the page to support different browsers.
Now open index.html in your web browser and you should see the text “Hello World”.
Say It With Style
If you look carefully at the above code, you’ll notice I’m including two style sheets. The first has some basic styles, and the second really brings on the style, so you will want to grab one or both stylesheets in order to get your UI looking neat. Place them in the appropriately named css folder, so now your file structure nests a js folder and a css folder under the BackboneTodos parent folder.
We still don’t have the actual todos shown on the page, so let’s add some HTML that will consist of a section where our Todos will be listed. We will also remove the line that reads <h1>Hello World!</h1>, we don’t need it now. Instead, we will replace it with the following HTML.
This is the main section of our app where we are going to display Todos, mark todos as completed, as well as add and remove todos. Once you’ve added the new HTML, when you do a page refresh, this is what you should see.
If your app doesn’t look half as good, make sure you have downloaded the two style files I linked to in the repository above “index.css” and “blingstyles.css”. Once you’ve downloaded them, remember to include them in the head section of index.html using stylesheet tags.
See that giant input field that says “What needs to be done?”. Now you should try to enter some text in there for a todo. Press enter when you are done and see what happens.
Wait, nothing happened! That’s right, for that to happen we need the help of Backbone.js, so let’s actually create some code now that will add logic to save whatever text we type as a new todo item.
Backbone Collections, Models And Views
This is the part where you learn enough Backbone.js to get your hands dirty. Backbone is built around the MVC pattern, heavily inspired by Ruby on Rails and similar frameworks. It brings MVC to the browser in a very elegant way.
Take our Todo app for instance. Backbone has the notion of a Collection, which is a special Backbone class that will allow us to store all our todos in one grouping that we can update or filter to retrieve or set new information.
Individual Todos will be represented by a Model, which is a mirror of what our data looks like on the server or in a database. Here, we are using local storage instead of a database, but frequently, you will have a database on the server that you work with.
For each Model, there will also be a view, which presents the details of the Model to the user. The View does not change the Model directly. Rather the view fires off events, which are then responsible for changing the state of the model. The view also listens for changes to the model and the collection of models. When these change, then the view changes.
Now, let us create our Todo model, which will hold details about an individual Todo item. Think about what attributes a Todo needs to have:
It obviously needs a title, telling us what is to be done, as well as a status, whether the Todo has been completed or has not yet been completed. We could add more attributes to get fancy, but let’s go with these basic attributes for now.
Create a new file at the path BackboneTodos/js/models/todo.coffee containing the following definition of the Todo model.
In a terminal window, cd into your project’s root folder, and run the following:
Now let’s define a Collection that will hold Todo models. Create a new file at BackboneTodos/js/collections/todos.coffee. Inside that file, include the following definition of a Collection named TodoList, and an instantiation, finally, of such a collection.
Further, we are defining a completed method to filter for Todos that are complete, as well as a few other methods to allow us to query and update the list of Todos.
The next major piece we will want now is to include a router, which will allow us to filter and view specific subsets of our Todo collection. There are three filters we want to be able to see: all (shows all todos), completed (only shows completed todos) and active (only shows active todos).
So let’s create a new router file at BackboneTodos/js/router/router.coffee with the following
We have a Collection, we have a Model, but where is the View?
Before we get to the View part of MVC so we can see our app in all its bling, let’s set up our index.html to utilize the new code we just added, as well as pull in some as-yet undefined scripts that will set up the View.
Back in index.html, under our script tags we defined earlier, add the following script tags, before the closing </body> tag.
We’re pulling in the scripts we wrote earlier. You’ll also notice we’re pulling in 3 scripts that are currently missing.
In order to use these scripts, let’s first define a couple of templates, which Backbone will use to render new Todos and filter todos.
The first template defines the view for a new todo, which we will append to the main document when a user enters text for a todo. Add the following code to index.html, inside the body but before the first of the script tags.
Including the last part of the section defined earlier, it looks like the following:
The template is enclosed in a script tag, but we are giving it a type of “text/template” so it does not show immediately on the page. Rather, when the user clicks enter after typing a Todo, we will then use Backbone to add a li list item, containing the HTML in the defined template. As you can see, we will render the title of the Todo, as well as a checkbox showing if it’s complete or not, and a button that allows us to destroy the Todo.
We can now write the Backbone code that constructs the View for an individual todo, using the template defined above, and listens for events such as a user hitting the “enter” key. Create a new file at BackboneTodos/js/views/todos.coffee with contents as below.
Here’s the documentation about Backbone Views which you should study a bit to really see the elegance of what the above view code achieves, courtesy of Backbone. Now events and user interaction are handled for us thanks to the above.
We have a View defined for Todos, but we need to actually make an instance of the view to have all the functionality on the page. We will therefore create a main view of the application, which is what will create the individual Todo Views when a new Todo is entered in the input for new Todos. This view will also list all the existing Todo items in a list. So now create a new file at BackboneTodos/js/views/app.coffee which contains the definition of the main View.
In the above code, we are listening for events like keypress inside the input for a new Todo. Whenever there is a keypress, we delegate to the createOnEnter function. This is where we check to see if the key the user has pressed was the Enter key. If it is, we then take all the text the user has entered in the input, and create a new instance of the Todo model and save it. That causes a change to the TodoList collection, and in the newly defined view, we are also listening for changes to the collection, among other things. When a new Todo is added to the collection, we then create a new instance of the Todo View for individual Todo items, and append it to the todo list in our index.html identified by the code this.$(“#todo-list”) .
All that remains now is to instantiate our AppView defined above, which will set up the rest for us. So now create a new file at BackboneTodos/js/app.coffee, which will simply create a new AppView and allow us to fully interact with the app:
Now you should be able to enter a new Todo, as well as double click to edit an existing Todo. You can also delete a Todo by clicking on the button to the right of each Todo. But what about if we want to see only Completed or only Active Todos?
We already defined filter functions for this in our router file and our main view and the collection itself. So now, all that remains is to add a template at the bottom of the page with links pointing to routes that trigger the filters for completed or active Todos.
Back in index.html, below the template with an id of “item-template”, create a new template for the footer, with the following code
Now trying clicking on the links for Active or Completed or All todos. You should be able to see the route change, and to see only the todos that match the filter of “active” or “completed”. Here is the code repository on Github again if you need it.