18

I am new to Marionette.js and while I am refactoring my existing Backbone.js code, I noticed there are two callbacks on Marionette view (itemview) that looked to me similar, i.e. onRender and onShow. What is the difference and better way of using them ?

However, looking at source code, i think both "render" and "show" events are raised inside "view initialize".

constructor: function(){
    _.bindAll(this, "render");

    var args = Array.prototype.slice.apply(arguments);
    Backbone.View.prototype.constructor.apply(this, args);

    Marionette.MonitorDOMRefresh(this);
    this.listenTo(this, "show", this.onShowCalled, this);
}
Vitalii Petrychuk
  • 14,035
  • 8
  • 51
  • 55
addisu
  • 634
  • 1
  • 4
  • 12

4 Answers4

42

I think there is something not totally correct in Vitaliy's answer. The correct will be:

onShow : view itself doesn't trigger 'show' event. It triggers by a region. So it will not be called in some cases.

onRender : this method executes every time the view is rendered.

Note that 'onRender' being executed doesn't mean that the object is actually added to the DOM. It just means that it was just rendered (data filled the template, you have a this.$el to deal with, etc.)

On the other hand, if 'onShow' is called because the 'show' event has been triggered from a region, and as regions usually represent an element within the DOM, you might expect that when 'onShow' is called, the view is indeed added to the DOM.

Community
  • 1
  • 1
John Bernardsson
  • 1,751
  • 1
  • 17
  • 19
  • 1
    This is correct, the statement that onRender fires after an element has been inserted into the DOM is misleading and will confuse a lot of people. – Louis Simoneau Dec 11 '13 at 05:47
  • 2
    Why not just improve the answer? – Vitalii Petrychuk Jan 24 '14 at 07:03
  • 2
    Sorry, I didn't know I could do that :/ I just edit the answer and change it, or I need to do something more? Again, my apologies :( – John Bernardsson Jan 28 '14 at 17:13
  • For accessibility purposes, there are cases where you'll need to put focus on elements as soon as they are added to the DOM so screen readers can read their content. For example, when a loading spinner appears it may have text in its view, so you can use a bit of jQuery: `this.$('#spinner-title').focus();`. But I noticed the focus only actually takes place on `onShow` , not on `onRender`. This shows the difference between the two types of callbacks. – Belden Schroeder Aug 09 '15 at 15:48
  • There is one more available event, `onDomRefresh`, which gets called when the view is moved from the "shadow DOM", where all off-screen rendering happens for performance reasons, to the real DOM. – mix3d Nov 06 '15 at 21:42
20

onShow : view itself doesn't trigger 'show' event. It triggers by a region. So it will not be called in some cases.

onRender : this method executes every time the view is rendered.

Vitalii Petrychuk
  • 14,035
  • 8
  • 51
  • 55
  • However, looking at source code, i think both "render" and "show" events are raised inside "view initialize" .... ` constructor: function(){ _.bindAll(this, "render"); var args = Array.prototype.slice.apply(arguments); Backbone.View.prototype.constructor.apply(this, args); Marionette.MonitorDOMRefresh(this); this.listenTo(this, "show", this.onShowCalled, this); }` – addisu Jun 14 '13 at 19:31
  • 3
    No, `ItemView` (extends from `View`) just subscribes to the `show` event - `this.listenTo(this, "show", this.onShowCalled, this);` and doesn't trigger it. `render` event triggers inside the `render` method, not on the `view initialize`. So it can be called at any time manually. – Vitalii Petrychuk Jun 14 '13 at 19:36
  • Also, I don't think onRender is available on plain views -- only on itemviews. – Erik Jan 24 '14 at 02:02
7

Well, this is the show method in Marionette and it explains the question

show: function(view){

       this.ensureEl();

       var isViewClosed = view.isClosed || _.isUndefined(view.$el);

       var isDifferentView = view !== this.currentView;

       if (isDifferentView) {
         this.close();
       }

       view.render();

       if (isDifferentView || isViewClosed) {
         this.open(view);
       }

       this.currentView = view;

       Marionette.triggerMethod.call(this, "show", view);
       Marionette.triggerMethod.call(view, "show");
     }
addisu
  • 634
  • 1
  • 4
  • 12
0

In version 3 the region events show and before:show are no longer triggered on the view. You can use render and before:render events in most cases. If you need to know that the view is in the DOM then you can use attach or dom:refresh

info http://blog.marionettejs.com/2016/08/23/marionette-v3/index.html

zloctb
  • 10,592
  • 8
  • 70
  • 89