Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

After Render Event on CompositeView with Backbone.Marionette

I have a Marionette CompositeView with a search panel and the collection of result data.

I would like to call a function when:

  • the search panel is rendered.
  • the collection is not rendered yet.
  • this function should not be called when the collection is rendered.

I did it in this way: (but "afterRender" function get called twice)

// VIEW
App.MyComposite.View = Backbone.Marionette.CompositeView.extend({
    // TEMPLATE
    template: Handlebars.compile(templates.find('#composite-template').html()),
    // ITEM VIEW
    itemView: App.Item.View,
    // ITEM VIEW CONTAINER
    itemViewContainer: '#collection-block',

    //INITIALIZE
    initialize: function() {        
        this.bindTo(this,'render',this.afterRender);
    },

    afterRender: function () {
        //THIS IS EXECUTED TWICE...
    }

});

How can i do this?

==========================EDIT==================================

I solved it in this way, if you have an observation please let me know.

// VIEW
App.MyComposite.View = Backbone.Marionette.CompositeView.extend({

    //INITIALIZE
    initialize: function() {        
        //this.bindTo(this,'render',this.afterRender);
        this.firstRender = true;
    },

    onRender: function () {
        if (firstRender) {
            //DO STUFF HERE..............
            this.firstRender = false;         

        }
    }

});
like image 545
Jaime Rivera Avatar asked Aug 30 '12 22:08

Jaime Rivera


2 Answers

Marionette provides an onRender method built in to all of it's views, so you can get rid of the this.bindTo(this, 'render', this.afterRender) call:


// VIEW
App.MyComposite.View = Backbone.Marionette.CompositeView.extend({
    // TEMPLATE
    template: Handlebars.compile(templates.find('#composite-template').html()),
    // ITEM VIEW
    itemView: App.Item.View,
    // ITEM VIEW CONTAINER
    itemViewContainer: '#collection-block',

    //INITIALIZE
    initialize: function() {        
        // this.bindTo(this,'render',this.afterRender); // <-- not needed
    },

    onRender: function () {
        // do stuff after it renders, here
    }

});

But to get it to not do the work when the collection is not rendered, you'll have to add logic to the onRender method that checks whether or not the collection was rendered.

This largely depends on what you're trying to do with the rendering when no items are rendered from the collection.

For example... if you want to render a "No Items Found" message, you can use the built in emptyView configuration for the composite view.


NoItemsFoundView = ItemView.extend({
  // ...
});

CompositeView.extend({

  emptyView: NoItemsFoundView

});

But if you have some special code that needs to be run and do certain things that aren't covered by this option, then you'll have to put in some logic of your own.


CompositeView.extend({

  onRender: function(){
    if (this.collection && this.collection.length === 0) {
      // do stuff here because the collection was not rendered
    }
  }

});
like image 57
Derick Bailey Avatar answered Sep 17 '22 10:09

Derick Bailey


Just use onShow function

Backbone.Marionette.ItemView.extend({
  onShow: function(){
    // react to when a view has been shown
  }
});

http://marionettejs.com/docs/marionette.view.html#view-onshow

like image 32
nothing-special-here Avatar answered Sep 17 '22 10:09

nothing-special-here