Drew Bartlett
Drew Bartlett

Reputation: 1891

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>

Upvotes: 9

Views: 13560

Answers (4)

Aravinda VP
Aravinda VP

Reputation: 1

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.

Upvotes: 0

Vitaliy Trush
Vitaliy Trush

Reputation: 11

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()

Upvotes: 1

dombesz
dombesz

Reputation: 7899

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.

Upvotes: 8

kikuchiyo
kikuchiyo

Reputation: 3421

Try a this.delegateEvents() after you render the new content.

Upvotes: 12

Related Questions