Search code examples
templatesbackbone.jsbackbone-views

BackboneJs unable to render template in rendered template


I have two views and I want to render a second one inside the first one. I am doing this:

First view:

var EventContainer = Backbone.View.extend({
  el: '#sectionContainer',
  initialize: function() {
    this.render();
  },
  render: function() {
    var that = this;
    $.get('templates/home/eventContainer.html', function(data) {
        that.template = _.template(data, {}); //Option to pass any dynamic values to template
        $(that.el).append(that.template); //adding the template content to the main template.
    }, 'html');

    new EventList();

    return this;
  }
});

Template for the first view:

<div class="main-content pull-left">
    <ul id="eventList" class="event-list no-list-style no-padding"> </ul>
</div>

Second view:

var EventList = Backbone.View.extend({
  el: '#eventList',
  initialize: function() {
    var that = this;
    this.EventsCollection = new EventsCollection();
    this.EventsCollection.fetch({
        success: function(data) {
            that.collection = data;
            that.setTemplate();
        },
        error: function() {}
    });
  },
  setTemplate: function() {
    var that = this;
    $.get('templates/home/eventList.html', function(data) {
        that.template = _.template(data);
        that.render();
    }, 'html');
  },
  render: function() {
    var that = this;

    this.collection.each(function(eventData) {
        var eventTemplate = that.template(eventData.toJSON());
        console.log('---> ' + $(that.el));
        $(that.el).append(eventTemplate);
    });

    return this;

  }
});

Template for the second View:

<li class="event-item">
    <small><%= like_count%> </small>
</li>

When I try to render the second view, el is undefined.

What m I doing wrong?

Thanks.


Solution

  • If you have a look at this.el inside EventList#initialize, I think you'll find that it is undefined rather than the <ul> that you're expecting it to be. Why would that be? Where does #eventList come from? #eventList comes from EventContainer's template and that won't be in the DOM until this AJAX call:

    $.get('templates/home/eventContainer.html', ...)
    

    completes. That $.get won't complete until well after your new EventList();. When you instantiate your EventList, it will go looking for #eventList but won't find anything, that will leave you with this.el being undefined. Then later on, that $.get will return and #eventList will show up in the DOM; this is why $('#eventList') works.

    The easy solution is to defer instantiating your EventList until after you've added the necessary things to the DOM:

    $.get('templates/home/eventContainer.html', function(data) {
        that.template = _.template(data, {});
        $(that.el).append(that.template);
        new EventList(); // <-----------------------
    }, 'html');
    

    If you're going to do this, then you could make the dependency explicit by dropping the el from the EventList definition and specifying it when you create the view instead:

    $.get('templates/home/eventContainer.html', function(data) {
        that.template = _.template(data, {});
        $(that.el).append(that.template);
        new EventList({ el: that.$('#eventList') });
    }, 'html');