简体   繁体   中英

Backbone event click on table row

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

The reason it doesn't work

$('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.

The improvements

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM