Backbone.js: defining el manually vs. automatically with id

48 views Asked by At

My question is simple. Why does the following work (i.e. show an alert when the black square is clicked):

$(document).on('ready', function() {
 var MainView = Backbone.View.extend({
  
        el : "#id",
      
  events : {
   "click" : function() {
    alert("this works");
   }
  },

 });
 var main_view = new MainView();
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js">
</script>
<style>
  #id {
  width : 10vw;
  height : 10vh;
  background-color : #000000;
}
</style>
</head>
<body>
<div id="id">
</div>
</body>
</html>

but the following doesn't:

$(document).on('ready', function() {
 var MainView = Backbone.View.extend({
  
        id : "id",
      
  events : {
   "click" : function() {
    alert("this works");
   }
  },

 });
 var main_view = new MainView();
});
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.1/backbone-min.js">
</script>
<style>
  #id {
  width : 10vw;
  height : 10vh;
  background-color : #000000;
}
</style>
</head>
<body>
<div id="id">
</div>
</body>
</html>

From the backbone documentation website:

"this.el can be resolved from a DOM selector string or an Element; otherwise it will be created from the view's tagName, className, id and attributes properties".

Nothing here suggests that events will fail to bind if I don't set the el manually...

Moreover, inspecting the main_view objects after creation show that the el in both cases is ostensibly the same. Why doesn't the click get bound in the second example, when the el is extrapolated from the id? Is there some philosophy of backbone that I'm missing here?

1

There are 1 answers

1
mu is too short On BEST ANSWER

The documentation for el says this:

this.el can be resolved from a DOM selector string or an Element; otherwise it will be created from the view's tagName ...

Emphasis mine.

So if you have this in your view:

el: 'some-selector-string'

then Backbone will look up that selector in the DOM and use what it finds as the el: i.e. it will resolve the selector to a DOM node and use that node as the final el and Backbone assumes that it is working with an existing node.

If you have this:

id: 'id',
tagName: 'div',
...

in your view, then Backbone will create the el based on those properties. Note that it only says that it will create the el, nowhere does it say that that el will be added to the DOM. If Backbone creates the el then it expects you to add it to the page.

In both cases you'll have an el in your view but only the first case (el: 'selector') will give you an el that is actually on the page.

If you're going to let Backbone create the el from id, tagName, and friends, then you'll need to add the el to the page yourself. The common pattern looks like this:

// In the view...
render: function() {
    this.$el.html('whatever goes inside the el');
    return this;
}

// And then outside the view
var v = new YourView;
$('some-container-element').append(v.render().el);
// Now the el is on the page and usable ------^^

If you ask Backbone to create the el with id: 'some-id' in your view and you already have <div id="some-id"> on the page, then you end up with two #some-id nodes: one on the page and one that is only in your view. The view's events are always bound through the view's el so there won't be any events on the #some-id on the page.