Sense
Sense

Reputation: 181

Backbone.js: Binding event to template button

I'm building an application with Backbone.js where a list of items and a placeholder "new" item are displayed. The container is a view that holds all the sub-views and renders them.

I have searched for some time now but can't get it to work. The problem is that the "Add" button in the template is not firing the event. I guess it's because of the rendering taking place at a later point in time and so the event is not assigned. Reading other posts this should be taken care of by Backbone.js but it doesn't seem that way. Adding a jQuery event handler after render() does the job but I think that cannot be the solution.

Here's the relevant code of the view:

template: _.template($("#template-time-new").html()),
events: {
  'click #btn-new-time': 'onButtonNewClick'
},
render: function() {
  this.$el.html(this.template());

  return this;
},

onButtonNewClick: function() {
  return false; // in this case: prevent page reload
}

My template (jade):

script(type="text/template", id="template-time-new").
<h3>
  <label for="new-time-name" class="muted">Name:</label>
  <input id="new-time-name" type="text">
</h3>
<div class="time-inner">
  <form class="form-horizontal">
    <label for="new-time-start" class="muted">From:</label>
    <input id="new-time-start" type="datetime-local">

    <label for="new-time-end" class="muted">to</label> 
    <input id="new-time-end" type="datetime-local">

    <button class="btn" id="btn-new-time">
      Add
    </button>
  </form>
</div>

EDIT:

Here's the code from the parent view:

initialize: function() {
  this.newView = new TimeSpanNewView; // <---- the view that is not really working

  this.render();

  // bind event handlers
  this.collection.on('all', this.render, this);
  // fetch data
  this.collection.fetch();
},

render: function() {
  var self = this;

  self.$el.empty();

  if ( self.collection.length > 0 ) {
    self.collection.each(function(timespan) {
      var subView = new TimeSpanView({ // sub views for the items, everything fine here
        model: timespan
      });

      subView.render()
      self.$el.append(subView.el);
    });
  } else {
    self.$el.text("Nothing found.");
  }

  self.$el.append(self.newView.render().el);

  return self;
}

Upvotes: 2

Views: 3155

Answers (1)

Artem Volkhin
Artem Volkhin

Reputation: 1372

Removed previous comment. Well, you have to render it everytime, in render() of the parent view. But instead of doing self.$el.html(""); try self.$el.children().detach(). And add child view as

self.$el.append(self.newView.render().el);

Explanation: $el already contains your child view and you don't want to completely remove the child view. So you need to call detach() on this - it removes DOM object for child view from page but doesn't remove it entirely.

Upvotes: 2

Related Questions