如何从自定义块助手中插入模板以在Meteor中单独重新渲染?

时间:2013-11-24 02:53:39

标签: meteor handlebars.js

当我使用内置块帮助器#each时,book模板会在更改时单独重新呈现:

users = 
  _id: 'foo'
  books: [
    {name: 'book1'}
    {name: 'book2'}
  ]

<template name="user">
  {{#each books}}
    {{> book}}
  {{/each}}
</template>

<template name="book">
  <div>{{name}}</div>
</template>

更改数据后 - 第一个图书名称设置为'bookone'而不是'book1' - 只会重新呈现book模板(包含'book1'的div)。这是期望的行为。当我使用自定义块助手时,行为是不同的:

<template name="user">
  {{#each_with_id}}
    {{> book}}
  {{/each}}
</template>

<template name="book">
  <div data-id="{{_id}}">{{name}}</div>
</template>

Templates.user.each_with_id = (options) ->
  html = "
  for book, i in this.books
    this.name = book.name
    html += Spark.labelBranch i.toString(), ->
      options.fn this
  html

现在,当第一本书的名称发生变化时,整个user模板将被重新呈现。

1 个答案:

答案 0 :(得分:1)

它无法正常工作,因为内置each的实现基于cursor.observeChanges功能。如果不使用某种辅助集合,您将无法获得相同的结果。这个想法很简单。您似乎没有“books”集合,但您可以创建仅客户端缓存:

Books = new Meteor.Collection(null);

你需要像这样动态放置一些数据:

Users.find({/* probably some filtering here */}).observeCanges({
  added: function (id, fields) {
    _.each(fields.books, function (book, index) {
      Books.insert(_.extend(book, {
        owner: id,
        index: index,
      }));
    }
  },
  changed: function (id, fields) {
    Books.remove({
      owner:id, name:{
        $nin:_.pluck(fields.books, 'name')
      },
    });
    _.each(fields.books, function (book, index) {
      Books.update({
        owner : id,
        name  : book.name,
      }, {$set:_.extend(book, {
        owner : id,
        index : index,
      })}, {upsert:true});
    }
  },
  removed: function (id) {
    Books.remove({owner:id});
  },
});

然后,您可以使用适当的光标(例如,each_with_id而不是each代替Books.find({owner:Session.get('currentUserId')}, {sort:{index:1}});

{{1}}

您还可以查看this其他主题,该主题基本上涵盖了您所询问的同一问题。