2012-02-06 14 views
16

Estoy tratando de renderizar una colección Backbone.js como una lista select usando una plantilla Underscore.js, y la lista no se está llenando. Se muestra el elemento select, pero no hay options.Rendering Backbone.js Colección como una lista de selección

He confirmado que puedo pasar propiedades individuales a mi plantilla y representarlas como elementos label, por lo que el problema debe ser la forma en que trato de manejar la colección.

Aquí está mi código Backbone:

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(); 

Y mi plantilla:

<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> 

¿Alguna sugerencia?

+0

Comprueba dos veces el valor de 'esto' en tu función de renderizado: no veo que lo vincules al objeto Backbone. Puedes hacerlo con _.bindAll (esto, 'render') en tu función de inicialización. –

+0

Hmmm. Agregué eso justo arriba de 'this.render()' en mi extensión 'Backbone.View', pero no pareció hacer nada. Antes de publicar mi pregunta, hice 'console.log (this.rates)' y salió como 'child' con tres sub-objetos. Así que creo que estoy pasando un objeto de algún tipo con tres objetos anidados debajo, lo cual parece correcto. –

+0

@Factor: 'delegateEvents' en las versiones recientes de Backbone realiza el enlace por sí mismo (busque' method = _.bind (método, esto); 'inside' delegateEvents' en la [fuente más reciente] (http://documentcloud.github.com/backbone/backbone.js)) por lo que ya no necesita el habitual baile '_.bindAll' para inicia tus métodos 'initialize' –

Respuesta

34

Tienes un par de problemas diferentes.

  1. Su plantilla está tratando de poner los elementos <option> después de la <select> en lugar de en el interior ella. Esto producirá HTML no válido y el navegador lo eliminará una vez que obtenga algo de su plantilla.
  2. rates es una colección Backbone por lo que ya tiene acceso a Underscore'seach; envolverlo como _(rates) solo confunde Underscore y evita que ocurran iteraciones.
  3. Dentro de la iteración, rate es una instancia de modelo Backbone por lo que no tendrá una propiedad duration, debe decir rate.get('duration').

La plantilla debe ser de la misma familia:

<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> 

Demostración: http://jsfiddle.net/ambiguous/AEqjn/

Como alternativa, sólo puede corregir el error de anidación en la plantilla para producir HTML válido:

<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> 

y use toJSON() en su vista para alimentar datos brutos a su plantilla en lugar de a la colección misma :

var rate_select_template = _.template($("#rate_select_template").html(), { 
    rates: this.rates.toJSON(), 
    labelValue: 'Something' 
}); 

Demostración: http://jsfiddle.net/ambiguous/VAxFW/

creo que el último es lo que se proponían como que haría con un enfoque más estándar para trabajar con plantillas en la espina dorsal.

+6

Impresionante, gracias por las claras explicaciones. No puedo creer que me haya perdido el problema con el anidamiento 'select'. Ugh. Backbone.js parece que va a ser genial, pero es imposible encontrar ejemplos de cosas realmente básicas como esta. Están sucediendo muchas cosas en las aplicaciones de muestra, como la aplicación de tareas pendientes, y es difícil ver qué hace cada pieza. Aprecio la ayuda. :) –

+4

@Josh: Es agradable trabajar con una vez que descubras los patrones básicos, por supuesto, la única manera de descubrir los patrones básicos es hacer errores. –

Cuestiones relacionadas