Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p><strong>Edit</strong>: I have updated the code below both because it was fragile, and to put it in context so it's easier to test. I have also added a caution - in most cases, you will want to use @zorlak's or @englandpost's methods (see below).</p> <hr> <p>First of all, kudos to @zorlak for digging up my old question that nobody answered. I have since solved this with a couple of <a href="https://stackoverflow.com/a/13635726/406226">insights gleaned from @David Wihl</a> and will post my own solution. I will hold off on selecting the correct answer until others have a chance to weigh in.</p> <p>@zorlak's answer solves the autocomplete issue for a single field, but as stated in the question, I was looking for <strong>an array</strong> that would update reactively, and the autocomplete was just one example of what it would be used for. The advantage of having this array is that it can be used anywhere (not just in template helpers) and that it can be used multiple times in the code without having to re-execute the query (and the <code>_.pluck()</code> that reduces the query to an array). In my case, this array ends up in multiple autocomplete fields as well as validation and other places. It's possible that the advantages I'm putting forth are not significant in most Meteor apps (please leave comments), but this seems like an advantage to me.</p> <p>To make the array reactive, simply build it inside a <code>Meteor.autorun()</code> callback - it will re-execute any time the target collection changes (but only then, avoiding repetitive queries). This was the key insight I was looking for. Also, using the <code>Template.rendered()</code> callback is cleaner and less of a hack than the <code>set_typeahead</code> template helper I used in the question. The code below uses <a href="http://underscorejs.org/#pluck" rel="nofollow noreferrer">underscore.js's <code>_.pluck()</code></a> to extract the array from the collection and uses <a href="http://twitter.github.com/bootstrap/javascript.html#typeahead" rel="nofollow noreferrer">Twitter bootstrap's <code>$.typeahead()</code></a> to create the autocomplete.</p> <p><em>Updated code</em>: I have edited the code so you can try this with a stock <code>meteor create</code>d test environment. Your html will need a line <code>&lt;input id="typeahead" /&gt;</code> in the 'hello' template. <code>@Items</code> has the <code>@</code> sign to make <code>Items</code> available as a global on the console (<a href="http://www.meteor.com/blog/2013/04/04/meteor-060-brand-new-distribution-system-app-packages-npm-integration" rel="nofollow noreferrer">Meteor 0.6.0 added file-level variable scoping</a>). That way you can enter new items in the console, such as <code>Items.insert({name: "joe"})</code>, but the <code>@</code> is not necessary for the code to work. The other necessary change for standalone use is that the typeahead function now sets the source to a function (<code>-&gt;</code>) so that it will query <code>items</code> when activated instead of being set at rendering, which allows it to take advantage of changes to <code>items</code>.</p> <pre><code>@Items = new Meteor.Collection("items") items = {} if Meteor.isClient Meteor.startup -&gt; Meteor.autorun -&gt; items = _(Items.find().fetch()).pluck "name" console.log items #first result will be empty - see caution below Template.hello.rendered = -&gt; $('#typeahead').typeahead {source: -&gt; _(Items.find().fetch()).pluck "name"} </code></pre> <p><strong>Caution! The array we created is not <em>itself</em> a reactive data source.</strong> The reason that the typeahead <code>source:</code> needed to be set to a <em>function</em> <code>-&gt;</code> that returned <code>items</code> is that when Meteor first starts, the code runs before Minimongo has gotten its data from the server, and <code>items</code> is set to an empty array. Minimongo then receives its data, and <code>items</code> is updated You can see this process if you run the above code with the console open: <code>console.log items</code> will log twice if you have any data stored. </p> <p><code>Template.x.rendered()</code> calls don't don't set a reactivity context and so won't retrigger due to changes in reactive elements (to check this, pause your code in the debugger and examine <code>Deps.currentComputation</code> -- if it's <code>null</code>, you are not in a reactive context and changes to reactive elements will be ignored). But you might be surprised to learn that your templates and helpers will also not react to <code>items</code> changing -- a template using <code>#each</code> to iterate over <code>items</code> will render empty and never rerender. You could make it act as a reactive source (the simplest way being to store the result with <code>Session.set()</code>, or <a href="http://www.eventedmind.com/posts/meteor-build-a-reactive-data-source" rel="nofollow noreferrer">you can do it yourself</a>), but unless you are doing a very expensive calculation that should be run as seldom as possible, you are better off using @zorlak's or @englandpost's methods. It may seem expensive to have your app querying the database repetitively, but Minimongo is caching the data locally, avoiding the network, so it will be quite fast. Thus in most situations, it's better just to use</p> <pre><code> Template.hello.rendered = -&gt; $('#typeahead').typeahead {source: -&gt; _(Items.find().fetch()).pluck "name"} </code></pre> <p>unless you find that your app is really bogging down.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload