Is there a Marionette.js Event that fires after all items in a CollectionView are rendered?
Asked Answered
L

3

6

In Backbone.Marionette.js CollectionViews and CompositeViews, the onDomRefresh event fires when the DOM is initially rendered and ALSO any time that an item is added to the view's collection (this contributes to the dynamic / "live" nature of the views). In my case, I want to run a certain jQuery function, but due to the typical length of the collection, it would be better to only call this function once at the last render to prevent excess function calls to something I only want to do once after all models are rendered in the UI.

Is there a Marionette event with the appropriate timing for this use case?

Lantha answered 21/10, 2013 at 21:9 Comment(2)
#13529907 ? Edit: Oh sorry, didn't see that you were asking for CollectionView.Valedictory
No problem, also a CompositeView method would work, but not an itemView.Lantha
C
2

As of V2.4.1 http://marionettejs.com/annotated-src/backbone.marionette.html, it's now render:collection that you should be listening for after the CollectionView is done rendering the children.

_renderChildren: function() {
  this.destroyEmptyView();
  this.destroyChildren();

  if (this.isEmpty(this.collection)) {
    this.showEmptyView();
  } else {
    this.triggerMethod('before:render:collection', this);
    this.startBuffering();
    this.showCollection();
    this.endBuffering();
    this.triggerMethod('render:collection', this);

    if (this.children.isEmpty()) {
      this.showEmptyView();
    }
  }
},

I would recommend against using mexitalian's answer as checking if the children.length == the collection.length will fire twice in the method onAddChild().

Coridon answered 18/5, 2015 at 22:39 Comment(1)
I'm going to assume this is the latest and greatest, please someone let me know if it's wrong as I'm not using Marionette now.Lantha
I
7

I had been trying to use Erik's solution all afternoon but the "collection:rendered" event is never fired. After trawling though the source I see it does not exist anymore :(

But there is a rather easy way to get the behaviour desired.

From within a CollectionView use the onAddChild callback to do the following:

onAddChild : function() {
// Check all the models in the collection have their child views rendered
  if ( this.children.length == this.collection.length ) {
    // Now you could do something like
    this.trigger("collection:rendered");
  }
}

It works because the collection count goes up to its new length instantly while the children length is updated one at a time.

Pretty simple, it has made me happy :) Hope it helps someone else too.

Idelia answered 4/8, 2014 at 17:12 Comment(0)
I
3

You can listen to "collection:rendered". Here is what the CollectionView triggers when it is done rendering children:

this.triggerMethod("collection:rendered", this);

You can use this:

this.listenTo(myCollectionView, "collection:rendered", _awesomeCallback);

Of course you will need to change the above.

EDIT:

Here is the render method for a collection view:

render: function(){
    this.isClosed = false;
    this.triggerBeforeRender();
    this._renderChildren();
    this.triggerRendered();
    return this;
  }

this.triggerRendered() fires off this.triggerMethod("collection:rendered", this), so the collection will be rendered before "collection:rendered" is triggered.

Icken answered 21/10, 2013 at 23:39 Comment(2)
This isn't accurate... collection:rendered is fired before any items are rendered. As far as I can tell the only way to know when all items are rendered is to listen for itemview:item:rendered, keep a count and compare it to collection.lengthBottleneck
Added render() method code which shows that "collection:rendered" isn't fired until the children are rendered.Icken
C
2

As of V2.4.1 http://marionettejs.com/annotated-src/backbone.marionette.html, it's now render:collection that you should be listening for after the CollectionView is done rendering the children.

_renderChildren: function() {
  this.destroyEmptyView();
  this.destroyChildren();

  if (this.isEmpty(this.collection)) {
    this.showEmptyView();
  } else {
    this.triggerMethod('before:render:collection', this);
    this.startBuffering();
    this.showCollection();
    this.endBuffering();
    this.triggerMethod('render:collection', this);

    if (this.children.isEmpty()) {
      this.showEmptyView();
    }
  }
},

I would recommend against using mexitalian's answer as checking if the children.length == the collection.length will fire twice in the method onAddChild().

Coridon answered 18/5, 2015 at 22:39 Comment(1)
I'm going to assume this is the latest and greatest, please someone let me know if it's wrong as I'm not using Marionette now.Lantha

© 2022 - 2024 — McMap. All rights reserved.