Kevin O'Hara
Kevin O'Hara

Reputation: 337

Backbone.js - views within views and re-renders

I have a collection of items and I am building a simple interface that lists the items on the left, then shows the detail of the currently selected item on the right.

I am trying to render a ItemView for each item within a ItemsListView. I need to bind to the model's change event so that the ItemView is updated along with the ItemDetailView.

In my implementation below, when updating the model that is showing in the ItemDetailView, setting a new property on the model updates the ItemDetailView but not it's representation in the ItemView. I know that I am doing something silly. How can I re-implement this so that both are re-rendered?

P.S. I am trying to avoid re-rendering the List view every time. I'd like to re-render each ItemView in the list separately.

var Item = Backbone.Model.extend({

});

var Items = Backbone.Collection.extend({

  model: Item

});

var ItemView  = Backbone.View.extend({

  template: window.JST['item/list'],

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.bind('change', this.render);
  },

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

});

var ItemDetailView = Backbone.View.extend({

  el: $('.detail .grid'),

  template: window.JST['item/detail'],

  initialize: function() {
    _.bindAll(this, 'render');
    this.model.bind('change', this.render);
    this.render();
  },

  render: function() {
    $(this.el).html('').fadeOut('fast', function() {
      $(this.el).html(this.template(this.model.toJSON())).fadeIn();
    }.bind(this));
    return this;
  }

});

// for the Items collection
var ItemsView = Backbone.View.extend({

  el: $('.items ol.grid'),

  initialize: function() {
    _.bindAll(this, 'render');
  },

  render: function() {

    // need to put this as the first item in the list
    $(this.el).html('<li class="listHeader"></li>');

    // iterate over the collection and render each ItemView separately
    this.collection.each(function(l) {
      var lv = new ListView({ model: l, collection: this.collection });
      var html = lv.template(lv.model.toJSON());
      $(this.el).append(html);
    }.bind(this));
  }

});

Upvotes: 0

Views: 802

Answers (1)

McGarnagle
McGarnagle

Reputation: 102743

I think the problem (maybe not the only one?) is that you haven't set the el property on ItemView, so it doesn't know how to render itself. I'm not sure what the best way to fix this is. Maybe add the client ID to the template using <li id='<#= cid #>' ..., and then in the initialize function of ItemView, set el using this.el = "#" + this.model.cid; or something similar.

Upvotes: 1

Related Questions