A Meteor findOne query returns undefined in one template helper. In other template helpers, the same query works well

Suppose I have a Meteor collection called GameStatus . I have users with different roles, but I publish the GameStatus collection for all users. I just use the following in server / publications.coffee

 Meteor.publish 'gamestatus', -> GameStatus.find() 

For the two roles ("S" and "B") I have no problem when I use the following template helper (defined in the files client /views/seller.coffee and client / views / buyer.coffee )

 currentRound: -> return GameStatus.findOne().currentRound 

For them, I never get the following error.

 Uncaught TypeError: Cannot read property 'currentRound' of undefined 

But for another role ('admin'), using the same template helper (defined in the client / views / admin.coffee file ) gives the Uncaught TypeError show above. It works if I write:

 currentRound: -> return GameStatus.findOne()?.currentRound 

I understand why this works. I think the collection is not available at first when the page loads, and then becomes available. But why does this not happen for the other patterns shown above?

It would be very helpful if someone could help clarify this.

+7
javascript meteor
source share
1 answer

I believe that when the collection is ready, it will not always be consistent, so if you want to cover all your databases, always use the code for the case when the collection is not ready.

There is a quick and dirty way to work with non-ready collections and a more complex solution that you can find in the todos example.

A quick and dirty solution would look like this.

 currentRound: -> gameStatusrecord = GameStatus.findOne(); if(gameStatusRecord) gameStatusRecord.currentRound 

That will work. Until the collection is ready, currentRound will return null, and your template will display briefly and probably just display a space for the current round. So not a perfect user experience, but not a huge deal.

For a more complex solution, you can check if your subscription is ready for collection using the "ready" function. If the collection is not ready, you can display some other template, such as "loading", which ensures that the currentRound helper will never be called until the collection is ready.

For example, in the todos example, the client subscribes to the lists collection on line 24 ofdos.js:

 var listsHandle = Meteor.subscribe('lists', function () { 

It then defines a helper function for the list template on line 80 of todos.js

 Template.lists.loading = function () { return !listsHandle.ready(); }; 

Then, in the list template in the todos.html 20 line, it does not try to display any templates if listHandle is not ready.

 <h3>Todo Lists</h3> {{#if loading}} <div id="lists">Loading...</div> {{else}} <div id="lists"> {{#each lists}} <!--etc.--> 
+13
source share

All Articles