Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Backbone.Marionette onRender callback fires before view is rendered in browser?

The setting

I have Backbone.Marionette.ItemView which renders some content. When the content is rendered I'd like to apply a jQuery plugin which turns part of the view into a container with a scrollbar.

The scrollbar is implemented completely in javascript and upon initialization it has to check the height of the scroll-container as well as that of the content inside the container.

If the content is higher then the container, a scrollbar should be enabled.

The problem

While this all sounds simple, I've ran into a strange problem:

If I initialize my scrollbar plugin directly in the onRender callback it seems to think the .scroll-container element has a height 0 and maxHeight of 0.

If I wrap the initialization code inside a 0ms timeout though, everything works as it should, the .scroll-container element's height property is returned by jQuery correctly and the scrollbar plugin works great.

The code

onRender: function() {
  var that = this;
  setTimeout(function() {
    that.onLayout();
    var $scrollContainer = that.$el.find('.scroll-container'), 
        scrollPane = new ScrollPane($scrollContainer, {
          maxHeightProperty: 'maxHeight',
          scrollUpButton: false,
          scrollDownButton: false
        });
  }, 0);
},

The question

I'm assuming the problem occurs because the browser didn't finish actually rendering the newly inserted html when the onRender callback is executed.

Is this assumption correct? And if so, is my solution of using a 0ms timeout reliable under normal circumstances?

like image 997
Ruben Vreeken Avatar asked Aug 08 '12 23:08

Ruben Vreeken


1 Answers

Since the plugin in question depends on the DOM, onRender won't do what you need. This callback kicks off after the view has been rendered, but there is no guarantee that the view's el has been added to the DOM yet. In fact, you are safe assuming the opposite - that it has not been added yet.

If you're using a Marionette Region to show the view, you can implement an onShow method in your view. This method gets called by the region, after the region has added the view to the DOM. It was implemented specifically to handle this situation.

For a little more info on this, and on working with jQuery plugins in general, see this blog post: http://lostechies.com/derickbailey/2012/02/20/using-jquery-plugins-and-ui-controls-with-backbone/

like image 186
Derick Bailey Avatar answered Nov 12 '22 20:11

Derick Bailey