Reputation: 28780
I am using backbone.marionette and have the following CollectionView ItemView combination:
PlansListItemView = PlansApp.ItemView.extend
tagName: "tbody"
template: "#plansRow"
events:
'click th.expander': 'expandDocuments'
expandDocuments: (e) =>
# do stuff
PlansCollectionView = PlansApp.CollectionView.extend
tagName: "table"
itemView: PlansListItemView
I create the view from an initial collection of json that is embedded on the page. The events in the events hash work perfectly.
Then on a dropdown change event, I call fetch() on the collection to retrieve a new collection of objects. The DOM gets rebuilt but the event handlers don't get reattached/
Has anybody any idea why this might happen?
Upvotes: 3
Views: 736
Reputation: 72868
Though I don't know the exact cause off-hand, there's some funny stuff in your setup that makes me think it might be part of the problem.
NOTE: I'm making some HUGE assumptions about your code and templates, based on what you've posted. Any number of things could be happening that would make much of what I'm saying invalid. Given what you've posted, though, here are my thoughts on how I would organize this code, which may help to clean up the problems your seeing.
Your setting up each item view as a <tbody>
tag, but then it looks like you have some <th>
tags rendered by that view - based on the event that you have configured, at least.
This is going to produce invalid HTML, such as:
<table>
<tbody>
<th></th>
</tbody>
</table>
It's hard to say without seeing the template for #plansRow
, but I would guess something like that comes out of this.
The problem is that collection views aren't good at generating tables. They can generate rows within a table just fine, and a table tag wrapper, but they won't be able to get the table headers, footer, body or other tags that a good table structure needs because collection views don't render a template of their own. They just create a wrapper tag and then render each of the children in the collection.
To correct this, use a CompositeView which is a CollectionView that also renders its own template.
A more appropriate setup for building tables with Marionette, is to use a CompositeView as the parent and have each item view render a tr
tag. For example:
RowView = Backbone.Marionette.ItemView.extend({
template: "#row-template",
tagName: "tr"
});
TableView = Backbone.Marionette.CompositeView.extend({
template: "#table-template",
tagName: "table",
appendHtml: function(cv, iv){
cv.$("tbody").append(iv.el);
}
});
This will set up a <table>
with the composite view. The template for that view would then contain the appropriate <thead><th>...</th></thead><tbody></tbody>
tags to define the table.
The row view renders as a <tr>
tag, and populates with whatever data it needs, including the appropriate <td>
tags.
The appendHtml
method on the composite view handles inserting each of the item views in to the <tbody>
tag of the parent composite view.
You can see a live version of this in this JSFiddle: http://jsfiddle.net/derickbailey/me4NK/
and a blog post to go along with this and other uses of the CompositeView, here: http://lostechies.com/derickbailey/2012/04/05/composite-views-tree-structures-tables-and-more/
Upvotes: 1