I'm trying to figure out how to conditionally send data to the client in meteor. I have two user types, and depending on the type of user, their interfaces on the client (and thus the data they require is different).
Lets say users are of type counselor
or student
. Every user document has something like role: 'counselor'
or role: 'student'
.
Students have student specific information like sessionsRemaining
and counselor
, and counselors have things like pricePerSession
, etc.
How would I make sure that Meteor.user()
on the client side has the information I need, and none extra? If I'm logged in as a student, Meteor.user()
should include sessionsRemaining
and counselor
, but not if I'm logged in as a counselor. I think what I may be searching for is conditional publications and subscriptions in meteor terms.
Use the fields option to only return the fields you want from a Mongo query.
Meteor.publish("extraUserData", function () {
var user = Meteor.users.findOne(this.userId);
var fields;
if (user && user.role === 'counselor')
fields = {pricePerSession: 1};
else if (user && user.role === 'student')
fields = {counselor: 1, sessionsRemaining: 1};
// even though we want one object, use `find` to return a *cursor*
return Meteor.users.find({_id: this.userId}, {fields: fields});
});
And then on the client just call
Meteor.subscribe('extraUserData');
Subscriptions can overlap in Meteor. So what's neat about this approach is that the publish function that ships extra fields to the client works alongside Meteor's behind-the-scenes publish function that sends basic fields, like the user's email address and profile. On the client, the document in the Meteor.users
collection will be the union of the two sets of fields.
Meteor users by default are only published with their basic information, so you'll have to add these fields manually to the client by using Meteor.publish. Thankfully, the Meteor docs on publish have an example that shows you how to do this:
// server: publish the rooms collection, minus secret info.
Meteor.publish("rooms", function () {
return Rooms.find({}, {fields: {secretInfo: 0}});
});
// ... and publish secret info for rooms where the logged-in user
// is an admin. If the client subscribes to both streams, the records
// are merged together into the same documents in the Rooms collection.
Meteor.publish("adminSecretInfo", function () {
return Rooms.find({admin: this.userId}, {fields: {secretInfo: 1}});
});
Basically you want to publish a channel that returns certain information to the client when a condition is met, and other info when it isn't. Then you subscribe to that channel on the client.
In your case, you probably want something like this in the server:
Meteor.publish("studentInfo", function() {
var user = Meteor.users.findOne(this.userId);
if (user && user.type === "student")
return Users.find({_id: this.userId}, {fields: {sessionsRemaining: 1, counselor: 1}});
else if (user && user.type === "counselor")
return Users.find({_id: this.userId}, {fields: {pricePerSession: 1}});
});
and then subscribe on the client:
Meteor.subscribe("studentInfo");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With