Listing 2. appointments.js $(document).ready(function () { Appointment = Backbone.Model.extend({ url : function() { var base = '/appointments/'; if (this.isNew()) return base; return base + this.id + '.json'; } }); Appointments = Backbone.Collection.extend({ model: Appointment, url: "/appointments.json", update_appointment_counter: function() { $("#number-of-appointments").html(this.length); }, initialize: function(models, options) { this.bind("add", options.view.add_appointment_row); this.bind("add", this.update_appointment_counter); } }); AppController = Backbone.Controller.extend({ routes: { "" : "index" }, index: function() { appview.appointments.fetch({ success: function(response) { appview.appointments.each(function(item) { appview.add_appointment_row(item); } ); $("#number-of-appointments").html(appview.appointments.length); }, error: function(response) { alert("error loading!"); } }); } }); AppView = Backbone.View.extend({ el: $("body"), initialize: function() { this.appointments = new Appointments(null, {view:this}); }, events: { "click #add-appointment": "add_appointment" }, add_appointment: function() { var person = $("#new-appointment td input[name=person]").val(); var starts_at = $("#new-appointment td input[name=starts_at]").val(); var note = $("#new-appointment td input[name=note]").val(); var new_appointment = new Appointment({person: person, starts_at: starts_at, note: note}); this.appointments.add(new_appointment); new_appointment.save(); }, add_appointment_row: function(model) { $("#appointments").append("" + model.get('person') + "" + "" + model.get('starts_at') + "" + "" + model.get('note') + ""); } }); var appview = new AppView; var myController = new AppController; Backbone.history.start(); });