Search code examples
javascripteventsbackbone.js

View Events not firing on created elements?


Trying to create a todo example app to mess around with backbone. I cannot figure out why the click event for the checkbox of a task is not firing. Here is my code for the TaskCollection, TaskView, and TaskListView:

$(document).ready(function() {

Task = Backbone.Model.extend({});

TaskCollection = Backbone.Collection.extend({
    model: 'Task'
});

TaskView = Backbone.View.extend({
    tagName: "li",
    className: "task",
    template: $("#task-template").html(),
    initialize: function(options) {
        if(options.model) {
            this.model = options.model
        }
        this.model.bind('change',this.render,this);
        this.render();
    },
    events: {
            "click .task-complete" : "toggleComplete"
    },
    render: function(){
        model_data = this.model.toJSON();
        return $(_.template(this.template, model_data));
    },
    toggleComplete: function() {
        //not calling this function
        console.log("toggling task completeness");
    }
});

TaskListView = Backbone.View.extend({
    el: $("#task-list"),
    task_views: [],
    initialize: function(options) {
        task_collection.bind('add',this.addTask,this);
    },
    addTask: function(task){
        task_li = new TaskView({'model' : task});
        this.el.append(task_li.render());
        this.task_views.push(task_li);
    },
});
});

Template for the task:

<script type='text/template' id='task-template'>
  <li class="task">
        <input type='checkbox' title='mark complete' class='task-check' />
        <span class='task-name'><%= name %></span>
      </li>
</script>

I can't seem to figure out why the toggleComplete event will not fire for the tasks. how can I fix this?


Solution

  • The problem here is that the backbone events only set to the element of the view (this.el) when you create a new view. But in your case the element isn't used. So you have the tagName:li attribute in your view, which let backbone create a new li element, but you doesn't use it. All you return is a new list element created from your template but not the element backbone is creating, which you can access by this.el

    So you have to add your events manually to your element created by your template using jQuery or add your template as innerHtml to your element:

    (this.el.html($(_.template(this.template, model_data)))