当我使用内置块帮助器#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
模板将被重新呈现。
答案 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其他主题,该主题基本上涵盖了您所询问的同一问题。