Backbone.View "el" confusion

68,245

Solution 1

A views el is where all the event binding takes place. You don't have to use it but if you want backbone to fire events you need to do your rendering work on the el. A views el is a DOM element but it does not have to be a pre-existing element. It will be created if you do not pull one from your current page, but you will have to insert it into the page if you ever want to see it do anything.

An example: I have a view that creates individual items

window.ItemView = Backbone.View.extend({
    tagName: "li", //this defaults to div if you don't declare it.
    template: _.template("<p><%= someModelKey %></p>"),
    events: {
         //this event will be attached to the model elements in
         //the el of every view inserted by AppView below
        "click": "someFunctionThatDoesSomething"
    },
    initialize: function () { 
        _.bindAll(this, "render");
        this.render();
    },
    render: function () {
        this.el.innerHTML = this.template(this.model.toJSON());
        return this;
    }
});
window.AppView = Backbone.View.extend({
    el: $("#someElementID"), //Here we actually grab a pre-existing element
    initialize: function () { 
        _.bindAll(this, "render");
        this.render(new myModel());
    },
    render: function (item) { 
        var view = new ItemView({ model: item });
        this.el.append(view.render().el);
    }
});

The first view just creates the list items and the second view actually places them on the page. I think this is pretty similar to what happens in the ToDo example on the backbone.js site. I think convention is to render you content into the el. So the el serves as a landing place or a container for placing your templated content. Backbone then binds its events to the model data inside of it.

When you create a view you can manipulate the el in four ways using el:, tagName:, className:, and id:. If none of these are declared el defaults to a div without id or class. It is also not associated with the page at this point. You can change the tag to something else by using using tagName (e.g. tagName: "li", will give you an el of <li></li>). You can set the id and class of el likewise. Still el is not a part of your page. The el property allows you to do very fine grain manipulation of the el object. Most of the time I use an el: $("someElementInThePage") which actually binds all the manipulation you do to el in your view to the current page. Otherwise if you want to see all the hard work you have done in your view show up on the page you will need to insert/append it to the page somewhere else in your view (probably in render). I like to think of el as the container that all your view manipulates.

Solution 2

Bit old now, but I was confused as well, and so for other people that get here, this fiddle might help - http://jsfiddle.net/hRndn/2/

var MyView = Backbone.View.extend({

    events: {
        "click .btn" : "sayHello",
    },

    sayHello : function() {
        alert("Hello");
    },


    render : function() {
        this.$el.html("<input type='button' class='btn' value='Say Hello'></input>");

    }
});

$(function() {
    myView = new MyView({el:"#parent_id"});
    myView.render();
});

Solution 3

You want your 'el' to reference an element that contains a child element that has any event that triggers a change in your view. Could be as wide as a "body" tag.

Share:
68,245
Manuel Meurer
Author by

Manuel Meurer

I'm the founder of Uplink, a network for IT freelancers in Germany: https://uplink.tech/ Uplink is a simple, fair, and transparent alternative to classic IT recruiters. If you're a freelancer (or a company looking for freelancers) and tired of recruiters wasting your time, come join us! :)

Updated on August 20, 2022

Comments

  • Manuel Meurer
    Manuel Meurer over 1 year

    How should a view's el be handled? It has to be set, otherwise events don't fire (see here).

    But should it be an element that is already on the page? In my app, I render a (jQuery Templates) template into a Fancybox. What should the el be in that case?

  • Manuel Meurer
    Manuel Meurer about 13 years
    Hmm, that doesn't really clear it up either. Most of the times the elements that could trigger a change in my view are inside the template the view renders, so before it is rendered these elements don't exist yet.
  • Manuel Meurer
    Manuel Meurer about 13 years
    Thanks for the clarification and the example! I think it is not always clear what the el should be in certain situations and the developer has to get a "feel" for it. Your explanations certainly helped! One question, though: you don't define an el in your ItemView, but you access it in the render function. Will this work? Is there some kind of default el if you don't explicitly define it?
  • LeRoy
    LeRoy about 13 years
    By default el is a "div" tag with no id or class. It is a DOM object not bound to your page DOM. Usually I insert/append it to the page in the render function or the render function of a parent view.
  • LeRoy
    LeRoy about 13 years
    Updated my answer with some description of the properties that define the el.
  • Scott Coates
    Scott Coates about 12 years
    I guess my only issue with grabbing a pre-existing element with el: $("#someElementID") is your view probably knows more than it should, making it difficult to reuse it. see "Decouple view from DOM..." coenraets.org/blog/2012/01/…
  • Metagrapher
    Metagrapher almost 12 years
    @scoarescoare since you are adding the el property on instantiation the view itself does not actually know more than it should, it remains modular and able to accept any $(el) you want to hand it. So this makes it quite reusable, really.
  • Scott Coates
    Scott Coates almost 12 years
    @Metagrapher - check out the blog link I supplied. It describes how this view is quite coupled to the DOM making reusability difficult. Consider if another page uses a different ID such as #someElementID2"
  • Metagrapher
    Metagrapher almost 12 years
    The AppView is coupled to the DOM, yes, but the ItemView is not. I think I was reading this incorrectly on the first go. Instead of putting the el declaration in the definition of AppView, it should be in the instantiation of the AppView. Of course, you can always override the default by defining it yourself on instatiation. I don't think this practice is that bad. If you have a page that uses the same elem id, then just call for a different one. It's good to provide a default.
  • Metagrapher
    Metagrapher almost 12 years
    It would probably be better to define a className and a tagName though
  • J.J.
    J.J. about 11 years
    I've followed this model and wish I had not. To destroy a view and remove the bindings, backbone's convention is view.remove(). That destroys $el and removes it from the DOM, so when you need to show the view again, $el does not exist.
  • afr0
    afr0 almost 11 years
    @Mark what If i'm using composite architecture like marionette.... do i still need to have view's el?
  • vikki
    vikki about 10 years
    Since you're calling render inside ItemView's initialize fn, is there any need to call view.render() inside AppView's render?
  • Elise Chant
    Elise Chant over 8 years
    yeah, behind the scenes, Backbone creates an element node basically ``this.el = document.createElement(this.tagName);``` so imagine that your render function is actually doing this: render: function() { this.el = document.createElement(this.tagName); this.el.innerHTML = this.template(this.context); return this; },
  • Izzy
    Izzy almost 8 years
    your fiddle code doesn't work, as link should be jsfiddle.net/hRndn
  • Izzy
    Izzy over 7 years
    @Mahi Yes you are right. I probably pasted wrong link, sorry. This one works: jsfiddle.net/hRndn/127