2012-02-06 86 views
16

我想使用Underscore.js模板呈现Backbone.js集合作为select列表,并且列表未被填充。 select元素正在显示,但没有options渲染Backbone.js集合作为选择列表

我已确认我可以将单个属性传递到我的模板并将它们呈现为label元素,所以问题一定是我如何处理集合。

这里是我的骨干代码:

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

而且我的模板:

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

有什么建议?

+0

在渲染函数中仔细检查'this'的值 - 我没有看到你将它绑定到Backbone对象。你可以在你的初始化函数中用_.bindAll(this,'render')来完成它。 – 2012-02-06 01:15:15

+0

嗯。我在我的'Backbone.View'扩展中添加了'this.render()',但它似乎没有做任何事情。在我发布我的问题之前,我做了'console.log(this.rates)',并将它输出为具有三个子对象的'child'。所以我认为我传递了一个嵌套在它下面的三个对象的某种对象,这看起来是正确的。 – 2012-02-06 01:19:43

+0

@Factor:在最近版本的Backbone中的'delegateEvents'自己完成绑定(查找'method = _。在[latest source](http://documentcloud.github.com/backbone/backbone.js)中绑定(method,this);''delegateEvents''内部,所以你不再需要通常的'_.bindAll'跳舞开始你的'initialize'方法。 – 2012-02-06 01:46:53

回答

34

你有几个不同的问题。

  1. 您的模板是试图把<option>元素<select>而不是它。这将产生无效的HTML,并且一旦你从你的模板中获得任何东西,浏览器就会抛弃它。
  2. rates是Backbone集合,因此它已经可以访问Underscore'seach;将它封装为_(rates)只是混淆了Underscore并防止发生任何迭代。
  3. 在迭代中,rate是一个Backbone模型实例,所以它不会有duration属性,您必须说rate.get('duration')

你的模板应该看起来更像是这样的:

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

演示:http://jsfiddle.net/ambiguous/AEqjn/

或者,你可以修复你的模板嵌套错误产生有效的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> 

并在您的视图中使用toJSON()将原始数据提供给您的模板而不是集合本身:

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

演示:http://jsfiddle.net/ambiguous/VAxFW/

我认为后者正是您作为瞄准会更标准的方法来与骨干模板工作。

+6

太棒了,谢谢你的明确解释。不能相信我错过了'select'嵌套的问题。啊。 Backbone.js似乎会很棒,但不可能找到像这样一些真正基本的东西的例子。在todo应用程序等示例应用程序中有很多事情发生,并且很难看到每件作品的功能。我很感激帮助。 :) – 2012-02-06 02:17:06

+4

@Josh:一旦你弄清楚了基本模式,这是很好的,当然了解基本模式的唯一方法就是制作mistaeks。 – 2012-02-06 02:23:33