Reputation: 656
I created a view for table row, that i want to listen to any click on any cells in this row. This is how I implemented:
let ListItem = Backbone.View.extend({
events: {
'click tr': 'showDetails',
'click': 'showDetails'
},
template: function() {
return "<tr><td><img src=<%= imageUrl %> /></td><td class='name'><%= firstName %></td><td><%= lastName %></td><td><%= homeTown %></td><td><button type='button' id='ddd' class='btn btn-danger'>Delete</button></td></tr>";
},
render: function() {
var oTemplate = _.template(this.template());
this.$el.html(oTemplate(this.model.toJSON()));
$('table > tbody:last-child').append(this.$el.html());
return this;
},
showDetails: function() {
alert("*****");
},
hide: function(bToHide, index) {
index++;
if (!bToHide) {
$($('tr')[index]).show();
return;
}
$($('tr')[index]).hide();
this.rendered = true;
},
openActorView: function() {
window.open('/#actor/' + window.actorsCollection.indexOf(this.model), '_self');
}
});
After clicking the row\cells within, nothing happens. I listen to click on this view + click on the tr, but nothing happens.
Also, when add event to tr td
nothing happens ether.
Thanks for helping
Upvotes: 0
Views: 1453
Reputation: 17430
$('table > tbody:last-child').append(this.$el.html());
The jQuery .html()
function returns a string.
So you're creating a nice Backbone view, with easy to define event listeners, then you don't use it, you just take its string representation and dump it in the DOM, losing any event listeners previously bound.
First, there's no need to make the template a function, just use _.template
directly. I wrote another answer which provides additional information on how to use _.template
.
After that, don't use global selectors inside a view. It kills the purpose of a scoped component view. Let the parent view class deals with this.
let ListItem = Backbone.View.extend({
tagName: 'tr', // the list item is a `<tr>`
events: {
'click': 'showDetails'
},
template: _.template("<td><img src=<%= imageUrl %> /></td><td class='name'><%= firstName %></td><td><%= lastName %></td><td><%= homeTown %></td><td><button type='button' id='ddd' class='btn btn-danger'>Delete</button></td>"),
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
showDetails: function() {
console.log("show details event");
}
});
Make a list view that manages the table. This is the parent class that will put the list items into the DOM.
Instead of using the jQuery core function, use the Backbone view scoped alias this.$()
to cache the table body.
let ListView = Backbone.View.extend({
initialize: function() {
this.$body = this.$('tbody');
},
render: function() {
this.$body.empty();
this.collection.each(this.renderItem, this);
return this;
},
renderItem: function(model) {
var view = new ListItem({ model: model });
this.$body.append(view.render().el); // use the DOMElement
}
});
Then pass an existing table from outside the view.
new ListView({ el: 'table.my-table' }).render();
This is a super basic example and you should be aware that performance could be improved further and that it could leak memory if used as-is.
See how to improve list rendering performance with Backbone.
Upvotes: 2