I can't for the life of me figure out why nothing shows up client-side in this meteor app. I have tried all the advise in all the related topics and nothing seems to work. I'm using msavin:mongol and I don't even see the subscription on the client at all, despite console.log() debug output indicates that it is there with the current number of entries.
/imports/api/friends.js:
export const Friends = new Mongo.Collection('friends');
Friends.deny({ insert() { return true; }, update() { return true; }, remove() { return true; } }); // access to collections only through method calls
/imports/api/server/friends.js:
import { Meteor } from 'meteor/meteor';
import { Friends } from '../friends.js';
Meteor.publish('friends.all', function(){
return Friends.find();
})
/imports/ui/pages/friends.js:
import { Friends } from '/imports/api/friends.js';
import './friends.html';
Template.friends.onCreated(function() {
this.subscribe('friends.all');
});
Template.friends.helpers({
friends: ()=>{ return Friends.find(); }
});
/imports/ui/pages/friends.html:
<template name="friends">
<h1 class="ui header">Friends</h1>
{{#if Template.subscriptionsReady}}
<h2 class="ui heder">friends list:</h2>
<div class="ui list">
{{#each friend in friends}}
<div class="item">{{friend.name}} ({{friend.email}})</div>
{{/each}}
</div>
{{/if}}
</template>
The "friends list" header shows up, so the subscriptionsReady call returns, but I don't get any data (verified that data exists in the database).
I've also tried moving the subscription into the router (using ostrio:flow-router-extra) and there the waitOn() function never returns when I add the subscription
What is going on here?
If you are missing to include your publication on the server then your client's subscription will immediately be 'ready' but there will be no error message.
This can cause a lot of confusion when creating templates with template-level-subscriptions.
In order to check if a publication exists or not, you can use on the server after start the (undocumented) server.publish_handlers
array. It keeps a record of the registered publications.
Meteor.startup( () => {
console.log( Meteor.server.publish_handlers );
});
This comes in very handy, if you have designed your api in way that it keeps track of its intended publications:
friendsdef.js
// definition file for Friends collection and it's
// surrounding functionality
export const FriendsDef = {
collectionName: 'friends',
schema: { ... },
methods: { ... },
publications: {
all: {
name: 'friends.all'
}
}
}
someServerStartup.js
// make sure on startup, that all intended
// publications are registered
Meteor.startup( () => {
Object.values( FriendsDef.publications).forEach( pub => {
if (!Meteor.server.publish_handlers[pub.name]) {
throw new Error('publication should exist, but does not');
}
});
});
The same works with method_handlers
for methods. Use these data structures with a well defined API and you will decrease errors of missing includes or misspelled names a lot.