Reputation: 1586
I want to render a <select>
with <option>
's based on a collection using Marionette's ItemView. Because the options need to have actual "values" in order for my App to work, I'm a bit unsure as to how I get Marionette to handle this? If I set a tagName: 'option'
in my ItemView, I'm not sure how to add the option after rendering. I thought I could just let the <option value="<%= id %>">
in the template, but that causes a double <option>
element to render because I had already specified it in the tagName
attribute of my ItemView. What's a best practice for doing this? My template looks like this:
<script type="text/template" id="sport-item-view">
<option value="<%= id %>"><%= name %></option>
</script>
Upvotes: 3
Views: 3860
Reputation: 72858
Are you using a CollectionView as the parent view type to render the collection of models in to the select
? If you are, you shouldn't be.
Since the option
items need everything in attributes, rendering a template for each option becomes painful as you've already encountered. Instead, use a single ItemView
for the entire select
box. An ItemView can take a collection in to it, and you can access that collection at items
inside of the template. This makes it very trivial to create a select box out of a collection, with a single view:
<script type="text/html" id="select-template">
<% _.each(items, function(item){ %>
<option value="<%= item.id %>"><%= item.get("someValue") %></option>
<% }) %>
</script>
var SelectView = Marionette.ItemView.extend({
tagName: "select"
});
var s = new SelectView({
collection: myData
});
s.render();
The downside to this is that you only have 1 view for your select box, which means you have to read the selected value from the select box to figure out which model you are dealing with. But this is only a couple of lines of code, and it saves a ton of headache otherwise.
Upvotes: 7
Reputation: 14225
You can simply use attributes.
You can override constructor in this way:
constructor : function (options) {
this.attributes = {
value : options.model.id
};
ItemView.prototype.constructor.apply(this, arguments);
}
And your template will be like this:
<%= name %>
http://jsfiddle.net/vpetrychuk/6Bk9T/
Upvotes: 1
Reputation: 15673
Perhaps it's better to handle this type of view in a more traditional sense by just adding options after render or perhaps on a triggered event. Here is what I did to add options dynamically based on fetched data:
var mySelect = this.ui.mySelect; // a reference to select from ui hash
mySelect.html(''); //clear
//for each data item add an option
_.each(items, function (item) {
mySelect .append($('<option/>', {
value: item.id,
text: item.description
}));
});
Upvotes: 0