Backbone.js - Is This Button And Event Bound Correctly?
Solution 1:
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.
<html><head><scripttype='text/javascript'src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js'></script><scripttype='text/javascript'src='http://ajax.cdnjs.com/ajax/libs/underscore.js/1.1.4/underscore-min.js'></script><scripttype='text/javascript'src='http://cdnjs.cloudflare.com/ajax/libs/backbone.js/0.5.3/backbone-min.js'></script><scripttype='text/javascript'>
$(function() {
//initialize the contacts collection and add some contacts
contacts = newContacts();
contacts.add(newContact());
contacts.add(newContact());
//only need to render the ContactsView oncevar view = newContactsView({ collection: contacts });
$("body").append(view.render().el);
//adding a contact to the contacts list when the//button is clicked
$("#add-contact").click(function() {
contacts.add(newContact());
});
});
Contact = Backbone.Model.extend({
defaults: {
first_name: "John",
last_name: "Smith",
address: "123 Main St"
}
});
Contacts = Backbone.Collection.extend({
model: Contact
});
ContactRow = Backbone.View.extend({
initialize: function() {
_.bindAll(this, "render");
this.template = _.template($("#contact-row").html());
},
//every backbone view has a tagName. the default tagName is 'div'//we're changing it to a table rowtagName: 'tr',
render: function() {
$(this.el).html(this.template(this.model.toJSON()));
returnthis;
}
});
ContactsView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, "render");
this.headerTemplate = $("#contacts-table-header").html();
this.collection.bind("add", this.renderContact, this);
},
//the ContactsView element will be a tabletagName: 'table',
render: function() {
$(this.el).html(this.headerTemplate);
this.collection.each(function(contact) {
this.renderContact(contact);
}, this);
returnthis;
},
renderContact: function(contact) {
var contactView = newContactRow({ model: contact });
$(this.el).append(contactView.render().el);
}
});
</script><scripttype='text/template'id='contact-row'><td><%= first_name %></td><td><%= last_name %></td><td><%= address %></td></script><scripttype='text/template'id='contacts-table-header'><thead><th>First Name</th><th>Last Name</th><th>Address</th></thead></script></head><body><buttonid="add-contact">Add Contact</button></body></html>
Solution 2:
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 rendering
So your render function may look like:
render: function() {
$("#button-container").append("<button id='add_contact'>Add Contact</button>");
$(this.el).html(this.template);
this.delegateEvents(); // re-wire events matching selectors in the event hash
_(this.collection.models).each(function(contact) {
appendContact(contact);
}, this)
returnthis; // you should also do this so you can chain
},
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's el
. All of the selectors in that event hash are scoped to el
, so if #button-contianer
isn't a child of it the button#add_contact
selector will never find anything. As a proof of concept, try this: in your render method:
render: function() {
console.log($(this.el).find("button#add_contact").length) // get anything?
...
Solution 3:
_(this.collection.models).each(function(contact) {
appendContact(contact);
}, this)
This code won't work, because you don't have a variable named appendContact
. Should be:
_(this.collection.models).each(this.appendContact(contact), this);
Post a Comment for "Backbone.js - Is This Button And Event Bound Correctly?"