编辑:我已经更新了下面的代码,因为它很脆弱,并且把它放在上下文中以便更容易测试。我还添加了一个警告——在大多数情况下,您会想要使用@zorlak 或@englandpost 的方法(见下文)。
首先,感谢@zorlak 挖掘了我没有人回答的老问题。此后,我通过从@David Wihl 收集的一些见解解决了这个问题,并将发布我自己的解决方案。我会推迟选择正确的答案,直到其他人有机会参与进来。
@zorlak 的答案解决了单个字段的自动完成问题,但正如问题中所述,我正在寻找一个可以反应性更新的数组,而自动完成只是它的用途的一个例子。拥有这个数组的优点是它可以在任何地方使用(不仅仅是在模板助手中),并且它可以在代码中多次使用而无需重新执行查询(并且将_.pluck()
查询减少到一个数组) . 就我而言,这个数组最终出现在多个自动完成字段以及验证和其他地方。我提出的优势可能在大多数 Meteor 应用程序中并不显着(请留下评论),但这对我来说似乎是一个优势。
要使数组具有反应性,只需在Meteor.autorun()
回调中构建它 - 它会在目标集合更改时重新执行(但只有这样,避免重复查询)。这是我一直在寻找的关键见解。此外,与我在问题中使用Template.rendered()
的模板帮助程序相比,使用回调更简洁,更少黑客攻击。set_typeahead
下面的代码使用underscore.js_.pluck()
从集合中提取数组,并使用Twitter 引导程序$.typeahead()
创建自动完成。
更新代码:我已经编辑了代码,因此您可以使用 stock meteor create
d 测试环境进行尝试。您的 html 将需要<input id="typeahead" />
在“hello”模板中添加一行。@Items
有在控制台上作为全局可用的@
标志( Meteor 0.6.0 添加了文件级变量范围)。这样您就可以在控制台中输入新项目,例如,但这并不是代码工作所必需的。独立使用的另一个必要更改是 typeahead 函数现在将源设置为函数 ( ),以便在激活时查询而不是在渲染时设置,这允许它利用对.Items
Items.insert({name: "joe"})
@
->
items
items
@Items = new Meteor.Collection("items")
items = {}
if Meteor.isClient
Meteor.startup ->
Meteor.autorun ->
items = _(Items.find().fetch()).pluck "name"
console.log items #first result will be empty - see caution below
Template.hello.rendered = ->
$('#typeahead').typeahead {source: -> _(Items.find().fetch()).pluck "name"}
警告!我们创建的数组本身并不是一个反应式数据源。source:
需要将 typeahead 设置为返回的函数 的原因是,当 Meteor 首次启动时,代码在 Minimongo 从服务器获取数据之前运行,并且设置为空数组。Minimongo 然后接收它的数据,并更新如果你在控制台打开的情况下运行上面的代码,你可以看到这个过程:如果你有任何数据存储,将记录两次。 ->
items
items
items
console.log items
Template.x.rendered()
调用不会设置反应性上下文,因此不会由于反应性元素的变化而重新触发(要检查这一点,请在调试器中暂停您的代码并检查Deps.currentComputation
- 如果是null
,则您不在反应性上下文中并更改到反应元素将被忽略)。但是您可能会惊讶地发现您的模板和帮助程序也不会对更改做出反应——用于迭代items
的模板将呈现为空并且永远不会重新呈现。你可以让它充当一个反应源(最简单的方法是用 存储结果,或者你可以自己做#each
items
Session.set()
),但除非您正在执行一个非常昂贵的计算并且应该尽可能少地运行,否则您最好使用@zorlak 或@englandpost 的方法。让您的应用程序重复查询数据库似乎很昂贵,但 Minimongo 将数据缓存在本地,避开网络,因此速度会非常快。因此,在大多数情况下,最好只使用
Template.hello.rendered = ->
$('#typeahead').typeahead {source: -> _(Items.find().fetch()).pluck "name"}
除非你发现你的应用程序真的陷入了困境。