Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rendering Backbone.js Collection as a select list

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?

like image 480
Josh Earl Avatar asked Feb 06 '12 01:02

Josh Earl


People also ask

Is Backbone JS still used?

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.

What is render in Backbone JS?

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.

What is the only method available in the backbone JS history?

There is only method named "start" can be used to manipulate the Backbone. js history.


1 Answers

You have a couple different problems.

  1. Your template is trying to put the <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.
  2. 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.
  3. Inside the iteration, 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.

like image 109
mu is too short Avatar answered Sep 22 '22 04:09

mu is too short