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:
create the view > render it > attach it:
view = new MyList().render()
$('#dummy').append(view.$el)
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?
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();
};