I'm experimenting with Backbone.js by creating a table view, and a seperate row view and trying to add the row to the table:
I have:
- A Contact model
- A Contacts collection
- A Contacts view (acts as the main view)
- A ContactRow view
So far, the project is working fine - except for a button that is supposed to trigger the function that adds the row.
Here is my code so far:
$(function($) {
window.Contact = Backbone.Model.extend({
defaults: {
first_name: "John",
last_name: "Smith",
address: "123 Main St"
}
});
window.Contacts = Backbone.Collection.extend({
model: Contact
});
window.ContactRow = Backbone.View.extend({
//el: $("#contacts-table table tbody"),
row_template: _.template($("#contact-row").html()),
initialize: function() {
_.bindAll(this, "render")
},
render: function() {
$("tbody").html("<tr><td>Look at me, I'm a row!</td></tr>");
return this;
}
});
window.ContactsView = Backbone.View.extend({
el: $("#contacts-container"),
events: {
"click button#add_contact": "addContact"
},
template: _.template($("#contacts-table").html()),
initialize: function() {
_.bindAll(this, "render", "addContact", "appendContact");
this.collection = new Contacts();
this.collection.bind("add", this.appendContact);
var contactRow = new ContactRow();
this.render();
this.appendContact(); // Just a test to see if the function is working
},
render: function() {
$("#button-container").append("<button id='add_contact'>Add Contact</button>");
$(this.el).html(this.template);
_(this.collection.models).each(function(contact) {
appendContact(contact);
}, this)
},
addContact: function() {
console.log("yup, it works!"); // well, not yet
var contact = new Contact();
this.collection.add(contact);
},
appendContact: function(contact) {
var contactRow = new ContactRow({
model: contact
});
$("body").append(contactRow.render().el);
}
});
var contactsView = new ContactsView();
}, jQuery);
As you can see, I have an addContact function that is tied to the click event of the "Add Contact" button that is being appended to a div element on the main page during the render process.
I'm attempting to write log messages to the console, but the button doesn't seem to be firing off the method and I can't figure out why.
It's the end of the day and my brain is fried so I'd appreciate any pointers on this. Thanks.
This is because you're appending
<button id='contact'>
after backbone has traversed your event collection.When you create a backbone view delegateEvents is called behind the scenes. This is where backbone looks at your events hash and wires everything up. To fix Either:
append
<button id='contact'>
before creating the viewor
or manually call backbone's
delegateEvents
after renderingSo your render function may look like:
Update:
It seems odd that you'd have to manually call
delegateEvents
. It could also be that#button-contianer
isn't a child of the view'sel
. All of the selectors in that event hash are scoped toel
, so if#button-contianer
isn't a child of it thebutton#add_contact
selector will never find anything. As a proof of concept, try this: in your render method:Here's a working example. I updated the code with best practices for using Backbone.
Notice I didn't add the button through a Backbone view. The button is part of the html body, and I just subscribe to its click event and then add a contact to the contacts collection.
This code won't work, because you don't have a variable named
appendContact
. Should be: