Search code examples
javascriptbackbone.jscoffeescriptbackbone-views

Get notified when a Backbone View has been rendered


I'm working on a Backbone.View which should render a collection as a scrollable list.

Part of the initial rendering, I need access to some layout properties (e.g. clientWidth) which are only available after the view has been rendered.

My problem is, how do I know when a view has been added to the DOM?


Using a Backbone.View there are typically 2 ways to attach a view to the DOM:

  1. create the view > render it > attach it:

    view = new MyList().render()
    $('#dummy').append(view.$el)
    
  2. create the view and render it in-place:

    new MyList({el: '#dummy'}).render()
    

Note: I know (1) and (2) are not completely equivalent, that's not the point.


Let's consider my list is defined something like this:

class MyList extends Backbone.View
    render: ->
        @$el->html( ... )
        @

    layout: ->
        max = $el.scrollWidth - $el.clientWidth
        # ... disable / enable scrolling arrows based on max ...

How would you make sure layout() is called after MyList is attached to DOM?


Solution

  • That's a deceptively difficult problem. There are DOM Mutation Events, but AFAIK these aren't implemented cross-browser and are deprecated anyway. Mutation Observers seem to be the new way to do it, but again, I'm not sure of the compatibility.

    A surefire, but expensive/messy way to do it is to poll to see if the body is somewhere in the ancestor chain.

    whenInserted = function ($el, callback) {
      check = function () {
        if ($el.closest('body').length) { // assuming a jQuery object here
          callback();
        } else {
          setTimeout(check, 100);
        }
      };
      check();
    };