Backbone click event not firing on dynamic view

13,512

Solution 1

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.

Solution 2

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

Solution 3

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

Share:
13,512
Drew Bartlett
Author by

Drew Bartlett

Updated on July 23, 2022

Comments

  • Drew Bartlett
    Drew Bartlett almost 2 years

    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>
    
  • Drew Bartlett
    Drew Bartlett over 10 years
    I tried adding that in and it didn't seem to change anything :(
  • Drew Bartlett
    Drew Bartlett over 10 years
    so if I run div.$el.find('a.change-status').trigger('click'); right after delegateEvents() it fires, but otherwise if I click it will not fire. Do you think it could have to do with that this is wrapped inside a couple other views? It's wrapped in a videoSet view that's then wrapped in a larger view. Would that effect this?
  • Drew Bartlett
    Drew Bartlett over 10 years
    nevermind, I had to render the parent view the same way as above, thanks!