Mdd
Mdd

Reputation: 4430

Why is the Backbone Views el undefined?

I am not sure why the el in my Backbone.View is undefined.

Here is a fiddle to my current code: http://jsfiddle.net/NC47C/

Here is the JavaScript:

var TheModel = Backbone.Model.extend({
  defaults: {
    color: 'Red',
    message: null,
    endOfLine: null
  }
});

var TheCollection = Backbone.Model.extend({
  model: TheModel,

  url: 'http://jsonstub.com/test/1'
});

var ParentView = Backbone.Model.extend({
  el: '.js-parent',

  initialize: function () {
    this.collection = new TheCollection();
    console.log(this.$el);

    return this;
  },

  myTemplate: function (scriptID, data) {
    var temp = _.template( $(scriptID).html(), {model: data} );

    this.$el.html(temp);

    return this;
  },

  render: function () {
    var self = this;

    this.collection.fetch({
        type: 'GET',
        beforeSend: function (request) {
            request.setRequestHeader('JsonStub-User-Key', 'xxxxxxxxxxxxx');
            request.setRequestHeader('JsonStub-Project-Key', 'xxxxxxxxxxxx');
        },
        success: function (data) {
            console.log( 'data =',data.toJSON() );

            self.myTemplate('#parentTemplate', self.collection);
        },
        error: function () {
            console.log('ERROR!!!');
        }
    });   

    return this;
  }

});

var parent = new ParentView();
parent.render();

Here is my HTML:

<script type="text/template" id="parentTemplate">
  <h1>hi</h1>
</script>


<div class="js-parent">

</div>

Upvotes: 0

Views: 3038

Answers (2)

cs_stackX
cs_stackX

Reputation: 1527

A few things might explain - My immediate hunch as to why the view $el is returning undefined is that because it is the parent view, the HTML in the template hasn't yet been created when the view is instantiated. As a result, it cannot find the class 'js-parent' in the DOM. Ways to get around this include:

1) Do your collection fetch in the view initialize function, then call render from within a collection fetch success callback.

See this answer from mu is too short (SO backbone king)

2) If that doesn't do it, try separating the creation and rendering of the view. You can append to a hardcoded (in your index.html) 'appWrapper' div element and then do:

 var parent = new ParentView(); 
 $('#appWrapper').html(parent.render().el);

3) Call render from within a jquery ready function (that would be desperate times).

As an additional note, where possible it's better practice not to define the $el within the view.

Finally, most backbone code I read uses this approach to template rendering: this.template(this.model.toJSON());

Upvotes: 1

bendtherules
bendtherules

Reputation: 382

Use el and $el consistently. This is something I found the hard way. I was reading about backbone from Addy Osmani's book. It mentioned that $el and el are the same thing, but when trying out it didnt turn out to be so. Maybe it was a change in newer versions of backbone, but I'm not sure.

Upvotes: 0

Related Questions