I'm trying to render a Backbone.js collection as a select
list using an Underscore.js template, and the list isn't getting populated. The select
element is displaying, but there are no options
.
I have confirmed that I'm able to pass individual properties into my template and render them as label
elements, so the issue must be how I'm trying to handle the collection.
Here's my Backbone code:
Rate = Backbone.Model.extend({
duration : null
});
Rates = Backbone.Collection.extend({
initialize: function (model, options) {
}
});
AppView = Backbone.View.extend({
el: $('#rate-editor-container'),
initialize: function () {
this.rates = new Rates(null, { view: this } );
this.rates.add(new Rate ({ duration: "Not Set" }));
this.rates.add(new Rate ({ duration: "Weekly" }));
this.rates.add(new Rate ({ duration: "Monthly" }));
this.render();
},
render: function() {
var rate_select_template = _.template($("#rate_select_template").html(), {rates: this.rates, labelValue: 'Something' });
$('#rate-editor-container').html(rate_select_template);
},
});
var appview = new AppView();
And my template:
<script type="text/template" id="rate_select_template">
<select id="rate-selector"></select>
<% _(rates).each(function(rate) { %>
<option value="<%= rate.duration %>"><%= rate.duration %></option>
<% }); %>
</script>
<div id="rate-editor-container"></div>
Any suggestions?
Backbone. Backbone has been around for a long time, but it's still under steady and regular development. It's a good choice if you want a flexible JavaScript framework with a simple model for representing data and getting it into views.
The Backbone. js render method overrides itself with your code that renders the view template from model data and updates this with new HTML. It contains the logic for rendering the template which constructs the view.
There is only method named "start" can be used to manipulate the Backbone. js history.
You have a couple different problems.
<option>
elements after the <select>
instead of inside it. This will produce invalid HTML and the browser will butcher that once you get anything out of your template.rates
is a Backbone collection so it already has access to Underscore's each
; wrapping it as _(rates)
just confuses Underscore and prevents any iterations from happening.rate
is a Backbone model instance so it won't have a duration
property, you have to say rate.get('duration')
.Your template should look more like this:
<script type="text/template" id="rate_select_template">
<select id="rate-selector">
<% rates.each(function(rate) { %>
<option value="<%= rate.get('duration') %>"><%= rate.get('duration') %></option>
<% }); %>
</select>
</script>
Demo: http://jsfiddle.net/ambiguous/AEqjn/
Alternatively, you can just fix the nesting error in your template to produce valid HTML:
<script type="text/template" id="rate_select_template">
<select id="rate-selector">
<% _(rates).each(function(rate) { %>
<option value="<%= rate.duration %>"><%= rate.duration %></option>
<% }); %>
</select>
</script>
and use toJSON()
in your view to feed raw data to your template rather than the collection itself:
var rate_select_template = _.template($("#rate_select_template").html(), {
rates: this.rates.toJSON(),
labelValue: 'Something'
});
Demo: http://jsfiddle.net/ambiguous/VAxFW/
I think the latter one is what you were aiming for as that would a more standard approach to working with templates in Backbone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With