简体   繁体   中英

Backbone click event not firing on dynamic view

I have a backbone view that creates a new div for each model that is passed into it. However, I cannot get any sort of events to fire (click a.change-status) on the view and I assume it's because the elements inside of it are also generated from a template. Please let me know if there's some way around this.

var videoDivView  = Backbone.View.extend({
el: '<div class="vendor-video" />',
initialize: function(){
    _.bindAll(this);
    this.render();
    this.model.on('change:published', this.enableSaveButton);
},
events: {
    'click a.change-status'     : 'changeVideoStatus'
},
template: video_tmpl,
render: function(){
    this.$el.attr("id", 'video-'+this.model.id);
    this.$el.html(this.template(this.model.toJSON()));
    this.$el.data('status', video_statuses[this.model.get('published')]);
},
changeVideoStatus: function(e) {
    console.log(this.model);
    return false;   
}, 
enableSaveButton: function() {
    $('#save-changes').removeClass('disabled').removeAttr('disabled');
}
});

an example template would look like:

<script id="single-video-tmpl" type="text/x-jquery-tmpl">
<div>
    <div class="video-info">
        <span class="video-title"><%=video_title%></span>
        <div class="bottom-info">
            <a href="#<%=id%>" class="change-status"></a>
        </div>
    </div>

</div>
</script>

渲染新内容后尝试使用this.delegateEvents()

There are some things that might be the cause of the problem.

First of all, your el declaration seems to be suspect. If you want a div with that class you just have to define the className attribute since the default for backbone views is div .

Instead of: el: '<div class="vendor-video" />'

just use: className: 'vendor-video'

I don't see any details about your view initialization methods but the best practice is to initialize a view and then render it to the container:

var yourVideoDivView = new videoDivView({model: model});
$("#your-video-container").html(yourVideoDivView.render().el)

also to get the last line work you have to return this; on your render method.

render: function(){
  ...
  return this;
}

About using this.delegateEvents() , you should call this function after your view is already in the DOM otherwise it makes no sense. ie:

$("#your-video-container").html(yourVideoDivView.render().el)
yourVideoDivView.delegateEvents();

delegateEvents() will makes your view events alive again.

I had a similar problem. You can resolve this problem in two steps.
- Create a tagName in view
- Append your template in this.$el
That's all. And it work without this.delegateEvents()

The issue I observed with tagName and appending using this.$el is, the event listener failed to attach the event for the last element created with selected tagName. But, the problem got solved when using this.delegateEvents() after appending the elements to DOM.

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