【问题标题】:Rendering Backbone.js Collection as a select list将 Backbone.js 集合呈现为选择列表
【发布时间】:2012-02-27 14:30:11
【问题描述】:

我正在尝试使用 Underscore.js 模板将 Backbone.js 集合呈现为 select 列表,但该列表没有被填充。 select 元素正在显示,但没有 options

我已经确认我能够将单个属性传递到我的模板中并将它们呈现为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>

有什么建议吗?

【问题讨论】:

  • 再次检查渲染函数中“this”的值 - 我没有看到您将它绑定到 Backbone 对象。您可以在初始化函数中使用 _.bindAll(this, 'render') 来完成。
  • 嗯。我在我的Backbone.View 扩展中将它添加到this.render() 的正上方,但它似乎没有做任何事情。在我发布我的问题之前,我做了console.log(this.rates),它输出为child,带有三个子对象。所以我想我正在传递某种对象,其中嵌套了三个对象,这似乎是正确的。
  • @Factor: delegateEvents 在 Backbone 的最新版本中自己进行绑定(在 delegateEvents 中查找 method = _.bind(method, this);latest source 中),因此您不再需要通常的 _.bindAll跳舞开始你的initialize 方法。

标签: javascript backbone.js underscore.js


【解决方案1】:

你有几个不同的问题。

  1. 您的模板试图将&lt;option&gt; 元素放在 &lt;select&gt; 之后,而不是放在 里面。这将产生无效的 HTML,一旦您从模板中获取任何内容,浏览器就会对其进行处理。
  2. rates 是一个 Backbone 集合,因此它已经可以访问 Underscore's each;将其包装为 _(rates) 只会混淆下划线并防止任何迭代发生。
  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/

我认为后一种是您的目标,因为这将是在 Backbone 中使用模板的更标准方法。

【讨论】:

  • 太棒了,感谢您的清晰解释。不敢相信我错过了select 嵌套的问题。啊。 Backbone.js 看起来会很棒,但是对于像这样的一些非常基本的东西,不可能找到示例。像 todo 应用程序这样的示例应用程序中发生了很多事情,而且很难看出每个部分的作用。我很感激帮助。 :)
  • @Josh:一旦你弄清楚了基本模式就可以很好地工作,当然,弄清楚基本模式的唯一方法就是犯错误。
猜你喜欢
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 2012-11-24
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-10
相关资源
最近更新 更多