lunacafu
lunacafu

Reputation: 366

Backbone.Marionette CompositeView optionlist

I'd like to create a CompositeView that contains a dropdown-list from a collection:

my views:

var ItemView = Backbone.Marionette.ItemView.extend({
    template: '#item-tpl'
});

var CompositeView = Backbone.Marionette.CompositeView.extend({
    template: '#comp-tpl',
    itemView: ItemView,
    itemViewContainer: '#mySelect'         
});

my templates:

<script id = "item-tpl" type="text/template">
    <option value="<%= id %>"><%= name %></option>
</script>

<script id = "comp-tpl" type="text/template">
   ...
          <form>
          <div class="control-group">
                <select id='mySelect'></select>
          </div>
         </form>

   ...
</script>

the rendered HTML displays the default div's, which break the options list

<select id="mySelect">
    <div>
        <option value="5">name 1</option>
    </div>
    <div>
        <option value="6">name 2</option>
    </div>
</select>

how can I achieve this:

<select id="mySelect">
    <option value="5">name 1</option>
    <option value="6">name 2</option>
</select>

Upvotes: 0

Views: 3111

Answers (2)

alexlopez
alexlopez

Reputation: 36

Is pretty easy actually the only thing you need to do is wrap the "el" (element) with jquery so the view should look like this:

var aItemView = Backbone.Marionette.ItemView.extend({
..
..

  el: $('#mySelect'),

..

that avoid the default div and you can use only the elements you need. so will get this instead

<select id="mySelect">
  <option value="5">name 1</option>
  <option value="6">name 2</option>
</select>

Upvotes: 0

David Sulc
David Sulc

Reputation: 25994

I would use this technique: http://jsfiddle.net/c9Lrm/8/

Start by simplifying your template:

<script id = "item-tpl" type="text/template">
  <%= name %>
</script>

Then, you need to provide the information about the item view so it renders with the data you want:

var aItemView = Backbone.Marionette.ItemView.extend({
    template: '#item-tpl',
    tagName: "option",
    onRender: function(){
        this.$el.attr('value', this.model.get('id'));
    }
});

You specify the tagName attribute so it doesn't get rendered with the default div tag but uses the option tag you need. Then, when the option gets rendered, you need to set the value attribute, which you do with the onRender function.

Finally, here's your new composite view:

var aCompositeView = Backbone.Marionette.CompositeView.extend({
    template: '#comp-tpl',
    itemView: aItemView,  
    itemViewContainer: "select"   
});

We specify the itemViewContainer to tell Marionette where to put our item views. That way, there's no need for us to redefine appendHtml.

This solution is a lot cleaner, since we're using Marionette functionality instead of doing everything on our own... But of course, the other solutions will work also.

If you want to learn more about generating the proper HTML structure with Marionette, you might be interested in this blog post of mine: http://davidsulc.com/blog/2013/02/03/tutorial-nested-views-using-backbone-marionettes-compositeview/

Upvotes: 6

Related Questions