marcus
marcus

Reputation: 10096

Event does not bind when adding view dynamically

I have two simple views, one with a button that creates a view and append it to the page. The new view consists of a single list item with a link and an event to I need to bind to each list item. I think the problem here is the el object: What I have been reading the el object should be created automatically when it's not defined on construction of the view? See this fiddle

HTML:

<div id="main">
    <button type="button" class="add">Add view</button>
    <ul id="tasks" />
</div>

<script id="view-template-new-task" type="text/html">
    <li><a href="#" class="fire">Task</a></li>
</script>
​

JS:

var TaskView = Backbone.View.extend({
    events: {
        'click a.fire': 'fire'
    },
    fire: function() {
        alert('fire');
    },
    initialize: function() {
        this.template = _.template($('#view-template-new-task').html());
    },
    render: function() {
        $('#tasks').append(this.template());
    }        
});
var View = Backbone.View.extend({
    events: {
        'click button.add': 'addView'
    },
    addView: function(e) {
        var task = new TaskView();
        task.render();
    }
});
$(function() {
    var view = new View({
        el: $('#main')
    });
});​

Upvotes: 4

Views: 3305

Answers (1)

nikoshr
nikoshr

Reputation: 33364

Backbone automatically delegates events to the view element. As is, the el in your TaskView would point to an unattached div (the default el created by Backbone) and not to an element in your list.

The cure is simple : create your subview with its el set to a correct DOM node by setting a tagName to li and appending this element in your main view.

var TaskView = Backbone.View.extend({
    tagName: 'li',

    events: {
        'click a.fire': 'fire'
    },

    fire: function() {
        alert('fire');
    },

    initialize: function() {
        this.template = _.template($('#view-template-new-task').html());
    },

    render: function() {
        this.$el.html(this.template());
        return this;
    }        
});

var View = Backbone.View.extend({

    events: {
        'click button.add': 'addView'
    },

    addView: function(e) {
        var task = new TaskView();
        this.$('#tasks').append(task.render().el);
    }
});

And an updated Fiddle http://jsfiddle.net/BLP6J/31/

Upvotes: 5

Related Questions