I would to show a list of all users, in my template.
I have:
//publications.js
Meteor.publish('users', function() {
return Meteor.users.find({}, { fields: {username: 1, profile: 1} });
});
//router.js
Router.route('/users/add/:_id?', {name: 'users.add', controller: 'UserAddController'});
UserAddController = RouteController.extend({
subscriptions: function(){
return [ Meteor.subscribe('hospitals'),
Meteor.subscribe('roles'),
Meteor.subscribe('users') ];
},
action: function() {
this.render('addUser', {
data: function(){
return { hospital_id : this.params._id }
}
});
}
});
//client
Template.listUsers.helpers({
users: function() {
return Meteor.users.find({});
}
});
But the list keep showing only the current logged-in user. I have created a list of users using Account.createUser() function What am I doing wrong?
Thanks.
You have to subscribe to a publication using this.subscribe() in subscriptions hook:
// a place to put your subscriptions
subscriptions: function() {
this.subscribe('items');
// add the subscription to the waitlist
this.subscribe('item', this.params._id).wait();
}
Or use waitOn:
// Subscriptions or other things we want to "wait" on. This also
// automatically uses the loading hook. That's the only difference between
// this option and the subscriptions option above.
waitOn: function () {
return Meteor.subscribe('post', this.params._id);
}
By default, Meteor publishes the current user. I see that you have a addUser template and a listUsers template. The problem is that while addUser is subscribed to the users publication, listUsers is not (this would depend on what else you have in your router of course). To fix this, change the call to this.render to render the listUsers template. Then, your users helper should work, and you can render the information however you like.
I tested this with my own app (the Microscope project from DiscoverMeteor) and it worked for me. Hope it works for you too. Comment here if not, and be sure to accept this answer if it worked. =)
Related
I am building a chat and based on the chatroom selected by the currentUser, I want to publish messages with this function:
Meteor.publish('messages',function(){
return Messages.find(
{chatId: 'QMMjBgCvLcnLvJPvx'},
sort:{timestamp: -1}
});
});
Now the chatId is still hardcoded, but it needs to be dynamic. The chatId is passed in the URL(e.g..../chat/QMMjBgCvLcnLvJPvx). In the client based code I have used to read the chatId:
var chatId = Router.current().params._id;
Iron Router
But this doesn't work server side. Is there a way to send the chatId from the URL to the server so I use Meteor.publish as mentioned above. Any help appreciated :)
Pass in the variable when you subscribe I.e.
Meteor.subscribe("messages", {chatId: Session.get("current-room")})
In the publication:
Meteor.publish('messages',function(chatId){
return Messages.find(
{chatId: chatId},
sort:{timestamp: -1}
});
});
In your route, you can subscribe to a publication and pass a param inside waitOn which will cause the app to show your loading template until the subscription is ready and the chatId will be reactive.
Configure loading template:
Router.configure({
layoutTemplate:'templateName',
loadingTemplate: 'anotherTemplateName'
});
Your route:
Router.route('/chat/:_id',{
waitOn: function(){
return Meteor.subscribe('messages', this.params._id);
},
action: function(){
//render your template with data
this.render('templateName', {
data: function () {
//will return object to the template which you can use in both HTML and JS. Also necessary for the link.
return Somethings.findOne({_id: this.params._id})
}
})
}
});
Publication:
Meteor.publish("messages", function (chatId) {
//the chatId comes from our subscribe in our route
return Messages.find({chatId: chatId});
});
Thanks for your answers and the hints. After some more modifications I arrived at this, which solved the issue:
var chatId = Router.current().params._id
this.wait(Meteor.subscribe('messages', chatId));
In my server folder I have a file where i'm doing the following
Meteor.publish("all_jobs", function(jobs) {
return Jobs.find();
});
Meteor.publish("user_jobs", function(user_id) {
return Jobs.find({userid: user_id}, {sort: {date: -1}});
});
On the user his blogpost page I do the following:
Session.set("userid", Meteor.userId());
Meteor.subscribe("user_jobs", Session.get("userid"));
Template.userJobs.helpers({
jobs: function(){
return Jobs.find();
}
});
On my homepage I would need all the blogpost. So i'm trying to access Meteor.subscribe("all_jobs");
The problem i'm having right now is that all the posts are showing up on my user profile instead of only the posts published by the user.
Any suggestions?
Thanks
When you make multiple subscriptions for the same collection, the results will be merged on the client. After subscribing to all_jobs, the client will now have all of the jobs in its local database until the subscription is stopped. When you go to find some of the jobs in the userJobs template, you will need to indicate which ones you actually are interested in. Modify your helper as follows:
Template.userJobs.helpers({
jobs: function() {
return Jobs.find(userid: Meteor.userId());
}
});
Found the problem. The problem was I was subscribed to all the publications because I just subscribed somewhere random in my code.
I fixed this by adding a waitOn in my route:
waitOn: function() {
return [
Meteor.subscribe("userJobs"),
];
},
In my Meteor app I have some collections I would like to subscribe to immediately upon login, and other collections I would like to subscribe to when the user visits or revisits the initial home page, but not otherwise.
The first set of collections should always be subscribed to throughout, but the second set should be turned off and on as the user leaves and returns to the initial screen.
I have the following code:
Meteor.startup(function () {
Meteor.subscribe('collection_one', Meteor.user().profile.setting_one);
Meteor.subscribe('collection_two', Meteor.user().profile.setting_two);
});
Router.route('/', {
name: 'home',
path: '/',
template: 'home',
waitOn: function() {
return [
Meteor.subscribe('collection_three', Meteor.user().profile.setting_three),
Meteor.subscribe('collection_four', Meteor.user().profile.setting_four),
]
}
});
My problem is that immediately upon startup and immediately upon going to the home page, Meteor.user() returns undefined. I would like to wait until Meteor.user() is defined, and then take these actions. How can I do this?
Meteor.startup() does not run code as a reactive computation, so even though Meteor.user() is a reactive data source it won't trigger a computation.
The reactivity section of the docs has a list of functions that run code as reactive computations.
You can use Tracker (previously called 'Deps') to create a reactive computation, like this:
Tracker.autorun(function () {
if (Meteor.user()) {
Meteor.subscribe('collection_one', Meteor.user().profile.setting_one);
Meteor.subscribe('collection_two', Meteor.user().profile.setting_two);
}
});
But it looks like you're using Iron Router so you could also set a global waitOn() with Router.configure to solve it, like this:
Router.configure({
layoutTemplate: 'MasterLayout',
loadingTemplate: 'Loading',
notFoundTemplate: 'NotFound',
templateNameConverter: 'upperCamelCase',
routeControllerNameConverter: 'upperCamelCase',
// This method will re-run when ever Meteor.user() changes.
waitOn: function () {
// Making sure setting_one and setting_two are available (which they won't be initially)
var setting_one = Meteor.user() && Meteor.user().profile && Meteor.user().profile.setting_one;
var setting_two = Meteor.user() && Meteor.user().profile && Meteor.user().profile.setting_one;
// Subscribe to the published version of the server side collections
return [
Meteor.subscribe('collection_one', setting_one),
Meteor.subscribe('collection_two', setting_two)
];
}
});
The key is to use Tracker.autorun()
import { Meteor } from 'meteor/meteor';
import { Tracker } from 'meteor/tracker';
let username = ''
Tracker.autorun( function(currentComputation) {
if (Meteor.user()) {
username = Meteor.user().username
if (username) // do something with username
return
}
})
currentComputation is optional
I'm using subscriptions manager with iron-router and my problem is this one.
I have a collection "participants" with 2 publications: allParticipants and todayParticipants.
if I go to this page:
Router.map(function () {
this.route('winners', {
waitOn: function () {
return [subs.subscribe('allWinners'),
subs.subscribe('allParticipants')];
console.log("subscribed!");
},
data: function () {
return {
winners: Winners.find(),
participants: Participants.find(),
loginBox: "True"
}
}
});
AllParticipants publication is subscribed and put in cache by the subscription manager package.
If after this, I go to this page:
Router.map(function () {
this.route('participants', {
path: '/',
waitOn: function () {
return subs.subscribe('todayParticipants');
},
data: function () {
return {
participants: Participants.find()
}
}
});
I'm expecting to subscribe only the todayParticipants but as my subscription is automatically named "Participants", It uses the cached subscription from the previous page being allParticipants.
Is there a way to change the name of my subscriptions in order to have each of them in the right cache?
Thanks.
What I do in my waitOn function is first stop my subscriptions like
if (App.subs) {
for (name in App.subs) {
App.subs[name].stop();
}
}
And then I create new subscriptions
App.subs = {
settings: Meteor.subscribe('settings', project),
...
};
return [App.sub.settings, .....];
Hope this helps!
Today, there seems to be no solution to this problem.
More explanation here: https://github.com/meteorhacks/subs-manager/issues/11
What I'm doing now is using a very limited number of subscriptions (filtered mainly on user) and then I create as much data objects as I want filtering my subscriptions in different ways.
Im new to Meteor and Im trying to figure out how to run a function after a collection change.
I have a route(iron router) that subscribes to a collection with waitOn. Which just waits for the subscrition to be ready before rendering which is what I want.
waitOn: function () {
return Meteor.subscribe('collection', this.params._id);
},
Any changes to the collection will be updated on all the clients and rendered automatically.
How would I run a function once the collection has changed?
You can use the onData hook, provided that you're returning that data using the data helper. E.g this is what a route may look like
this.route('routename',
path : '/abc',
waitOn: function () {
return Meteor.subscribe('collection', this.params._id);
},
data: function() {
return Collection.findOne({_id: this.params.id});
}
onData: function() {
//Do something when the data found by the above changes
}
});