0

UPDATE (RELEVANT DETAIL): This composite view is within a collection of composite views.

How can I construct the following HTML using a Backbone.Marionette composite view?

    <optgroup label="Group 1">
        <option>Item 1</option>
        <option>Item 2</option>
        <option>Item 3</option>
    </optgroup>
    <optgroup label="Group 2">
        <option>Item 4</option>
        <option>Item 5</option>
        <option>Item 6</option>
    </optgroup>

Since I want to avoid the <div> wrapper, I will have to specify <optgroup> as the tagName.

view = Backbone.Marionette.CompositeView.extend({
    collection: some_collection,
    itemView: some_itemview,
    template: '#some_template', <!-- What goes inside the template? -->
    itemViewContainer: 'optgroup',
    tagName:'optgroup', <!--specify to avoid the default div-->

    <!-- What should I specify in order to pass label="Group1" to the optgroup tag-->
});
snakesNbronies
  • 3,619
  • 9
  • 44
  • 73

3 Answers3

5

Don't use a CompositeView for this. You don't need a wrapper template since the wrapper in this case is only the <optgroup> tag.

Use a CollectionView instead, which doesn't render a wrapper template.

For the group #, use the onRender method


view = Backbone.Marionette.CollectionView.extend({
    collection: some_collection,
    itemView: some_itemview,
    tagName:'optgroup',

    onRender: function(){
      this.$el.attr("label", "Group 1");
    }

});
Derick Bailey
  • 72,004
  • 22
  • 206
  • 219
3

You could set the view element attributes in for example the initialize or onRender function, eg:

view = Backbone.Marionette.CompositeView.extend({
    ...

    initialize: function() {
        this.$el.attr('label', 'foobar');
    }
});

or replace initialize with:

    onRender: function() {
        this.$el.attr('label', 'foobar');
    }

OR

If you have an existing element such as:

<optgroup id="myGroup" label="Group 1">
</optgroup>

You can set the element of the view as such:

view = Backbone.Marionette.CompositeView.extend({
    el: $('#myGroup'),

    ...
});
lasse
  • 31
  • 2
  • Are the view options also a way of doing this? https://github.com/marionettejs/backbone.marionette/wiki/Passing-custom-options-to-itemview-from-collectionview-or-compositeview – snakesNbronies Dec 05 '12 at 09:46
  • just tried `this.$el.attr('label', this.model.get('name'))` within the initialize function, but am getting a reference error later on when I have declared a "start" function for the view - in which I render and then show within a region `$.when(mdvRendered).then(function(){ MyApp.modalDropdown.show(mdv); });` – snakesNbronies Dec 05 '12 at 10:20
  • 1
    Well `itemViewOptions` would be useful if you wanted to pass options to the ItemView:s, not the CompositeView. If you want to / are able to, you can pass the CompositeView with `Backbone.Marionette.CompositeView.extend({..., labelOption: "foobar"})` then for example inside initialize, use `this.options.labelOption`. Depending on how your code is structured, you can try move the `this.$el.attr('label', this.model.get('name'))` to a onRender function (I've edited the answer to show this). – lasse Dec 05 '12 at 13:45
2

A combination of Derick and Lasse's answers lead me to the solution. The onRender was what I was missing. Below is a summary for future readers.

The structure of the nested collection views:

Collection of Collections --> Collection --> Item
                          --> Collection --> Item
                          --> ... etc.

CollectionOfCollections =

Backbone.Marionette.CollectionView.extend({
    collection: myCollectionOfCollections,
    itemView: Collection <!--this refers to the next Collection view below-->
});

Collection =

Backbone.Marionette.CollectionView.extend({
    collection: myCollection,
    itemView: ItemView, <!-- again... the next view below -->
    tagName: 'optgroup',

Nested collections with Backbone.Marionette

    <!-- IF YOU ARE PASSING A SIMPLE ARRAY, 
    IT MUST BE CONVERTED TO A REAL COLLECTION FIRST -->

    initialize: function(){
       var xyz = this.model.get('abc');
       this.collection = new Backbone.Collection.extend({});
    });

    onRender: function(){

       <!-- Here's where you insert the attribute into the tag -->

       this.$el.attr('label', this.model.get('name'));
     }
   });
});

ItemView =

ModalDropdownEntryView = TourView.extend({
    model: myModel,
    template: '#myTemplate',
    tagName: 'option',
});
Community
  • 1
  • 1
snakesNbronies
  • 3,619
  • 9
  • 44
  • 73