[Solved] SpaceBars Bug..?


#1

Hello everyone,

I am using Spacebars #each loop in my project and i have noticed an anomaly.

I am querying data from mongoDb, returning the cursor in HTML, and then doing a #each on the cursor to display the return data as a table rows.

So, in my JS file

var a = 0; //Declared at the top of the JS file data(){ return db.find({}); }, counter() { // Counting how many times the code within the spacebars is run a++; console.log(a); array.push(this._id); }

In HTML

{{#each data}} <tr> <td class="column" id=“checkBox"><input class="userCheckboxes" type="checkbox" id=“checkbox"></td> <td class = "column" id=“value">{{data.value}}</td> </tr> {{counter}} {{/each}}

So my problem is, my database has 7 documents, but the counter function is run 8 times and i have 8 IDs in my array. The ID of the first document is inserted twice in the array, once in the beginning, once more in the end. But my table has only 7 rows of data.

I am not sure if this is by design or a bug, so i thought i’d ask.

What do you guys think. ??


#2

I guess this happens due to reactivity. At the beginning, your local client collection only contains one element (this would definitely be the case if db is your user database). Then, data is pushed to the client and the each block is run once again, now with all of the data. So in total, you get 8 runs.

In general, your way of retrieving the data is, erm, quite unusual. You should do this in an onCreated() block by subscribing to a publication. I recommend to have a closer look at the Meteor tutorials and the Meteor guide on how to do it correctly.


#3

Yes you are absolutely correct.
I was accessing the Users collection.Sorry, i should’ve specified this.
Anyways, in Meteor tools i did notice that i had only the current logged in user’s data was being shown from the database, until i moved to the page where this function/method was being run (Admin Dashbaord).

I had the data function/method as a template helper, but i will instead move it into onCreated() block with the subscription as per your suggestion.


#4

Ah, I thought you had it in the main code. A helper is fine, too, or even better for the actual find() method. Only the subscription should be placed in onCreated(). If you also do the find() there, you’ll have to put it inside an Tracker.autorun() block. I’d recommend this approach if you need the data in several helpers and would otherwise have to run the find() multiple times there.

The key point, however, is that you can’t rely on Meteor running the helper code only the exact number of times that matches the number of documents in your subscription. But Meteor will ensure that the rendered HTML will include only the number of elements matching your data. Putting an array push in such a helper is probably not the best idea.

If you need to store the data returned by find() in an array, I recommend to copy the results of find().fetch() directly into the array and place that code inside Tracker.autorun() in onCreated() or onRendered(). The subscribe() should be placed inside onCreated().