Search code examples
marionettebackbone-views

Nested composite views in marionette


When dealing with Marionettes different views, is it possible to have a composite view calling another composite view calling an item view? For instance, the structure could be a list of objects, each object having a list of attributes:

ObjectList = Marionette.CompositeView.extend({
    template: "#objectlist-template",
    childView: Object,
    initialize: function(){
    }
});

Object = Marionette.CompositeView.extend({
    template: "#object-template",
    childView: Attribute
    initialize: function(){
    }
});

Attribute = Marionette.ItemView.extend({
    template: "#attribute-template",
});

I tried doing this in my project, but it doesn't seem to work:

var objectListView = new ObjectList({
   collection: objects
});

How should the objects collection be structured?


Solution

  • This is totally possible, but you will need some extra wiring. I think it's generally not considered best practice to have a collection with models that have attributes that are another collection. I don't completely know your use-case so I will assume your attributes are just an array of strings and not something more complex.

    You should also refrain from using variable names like Object, Attribute, etc. as those clash with/are very close to reserved words. I renamed the views in my example.

    So mainly, in your ItemView you need to create the collection using an attribute of your model:

    var ItemListView = Marionette.CompositeView.extend({
        template  : "#objectlist-template",
        childView : ItemView
    });
    
    var ItemView = Marionette.CompositeView.extend({
        template   : "#object-template",
        childView  : ItemAttributeView
        initialize : function(){
            // Assuming 'itemAttributes' is something like ['red','yellow','green']
            var itemAttributes = this.model.get('itemAttributes');
    
            // Map itemAttributes to be objects to instantiate models
            // `name` can then be used in the attribute's template
            itemAttributes = _.map(itemAttributes, function(ia){ return { name : ia }; });
    
            // use this array to set the collection for this compositeview
            this.collection = new Backbone.Collection( itemAttributes );
        }
    });
    
    var ItemAttributeView = Marionette.ItemView.extend({
        template: "#attribute-template",
    });