1
votes

I am using Marionette's CollectionView to render a list of items with ItemViews. Whenever a new item is added, I want to run a short fade-in animation. But not when the collection is rendered initially (or the collection is reset).

Before using Marionette, I handled the reset and add events slightly differently, but I can not figure out how to do this here. I looked at the source code and it seems that addItemView is responsible for adding the child view and both addChildView (called when add is triggered on the collection) and render (for reset events) call this method.

Maybe I am missing something obvious.

3

3 Answers

5
votes

This is one way of doing it:

Include these functions in your CompositeView declaration:

onBeforeRender: function(){
  this.onBeforeItemAdded = function(){};
},

onRender: function(){
  this.onBeforeItemAdded = myAnimation;
}

This is similar to the solution I present in my book on Marionette (https://leanpub.com/marionette-gentle-introduction/)

How it works: Marionette triggers the "before:render" before it renders the entire collection, so you can set the the onBeforeItemAdded function to do nothing. Once the collection has been rendered, set that function to animate the new item view.

Since each time the collection view adds an item view it also triggers the "before:item:added", you can define an onBeforeItemAdded function that will automatically be called when that event is triggered. This matching happens thanks to triggerMethod.

This solution should solve your problem, without your needing to add flags on the model.

2
votes

David Sulc answer is pretty hacky, fadeIn should be defined within item it self, not within parent view. Another thing is that onBeforeItemAdded() is not mentioned in documentation, so it could be for internal use and may change over time.

What I suggest is to add following to parent view, note flag parentRendered:

    itemViewOptions: function() {
        return {
            collection: this.collection,
            parentRendered: this.rendered
        };
    },
    onRender: function() {
        this.rendered = true;
    }

and use that flag in onShow function inside item view:

    onShow: function() {
        // show visual effect on newly added items
        if (this.options.parentRendered) {
            this.$el.css('opacity', 0).slideDown(200).animate(
                { opacity: 1 },
                { queue: false, duration: 400 }
            );
        }
        else {
            this.$el.show();
        }   
    }
0
votes

I think that your best choice is to bind your event after the CollectionView has been rendered.

myCollectionView.on( "render", function() {
   this.on( "after:item:added", executeMyAnimation );
});