Skip to content Skip to sidebar Skip to footer

How Do You Conditionally Send Data To The Client In Meteor?

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

Solution 1:

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};
  elseif (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.

Solution 2:

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 () {
  returnRooms.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 () {
  returnRooms.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}});
  elseif (user && user.type === "counselor")
    return Users.find({_id: this.userId}, {fields: {pricePerSession: 1}});
});

and then subscribe on the client:

Meteor.subscribe("studentInfo");

Solution 3:

Because Meteor.users is a collection like any other Meteor collection, you can actually refine its publicized content like any other Meteor collection:

Meteor.publish("users", function () {
    //this.userId is available to reference the logged in user //inside publish functionsvar _role = Meteor.users.findOne({_id: this.userId}).role;
    switch(_role) {
        case"counselor":
            returnMeteor.users.find({}, {fields: { sessionRemaining: 0, counselor: 0 }});
        default: //studentreturnMeteor.users.find({}, {fields: { counselorSpecific: 0 }});
    }
});

Then, in your client:

Meteor.subscribe("users");

Consequently, Meteor.user() will automatically be truncated accordingly based on the role of the logged-in user.

Here is a complete solution:

if (Meteor.isServer) {
    Meteor.publish("users", function () {
        //this.userId is available to reference the logged in user //inside publish functionsvar _role = Meteor.users.findOne({ _id: this.userId }).role;
        console.log("userid: " + this.userId);
        console.log("getting role: " + _role);
        switch (_role) {
            case"counselor":
                returnMeteor.users.find({}, { fields: { sessionRemaining: 0, counselor: 0 } });
            default: //studentreturnMeteor.users.find({}, { fields: { counselorSpecific: 0 } });
        }
    });

    Accounts.onCreateUser(function (options, user) {
        //assign the base role
        user.role = 'counselor'//change to 'student' for student data//student specific
        user.sessionRemaining = 100;
        user.counselor = 'Sam Brown';

        //counselor specific
        user.counselorSpecific = { studentsServed: 100 };

        return user;
    });
}

if (Meteor.isClient) {
    Meteor.subscribe("users");

    Template.userDetails.userDump = function () {
        if (Meteor.user()) {
            var _val = "USER ROLE IS " + Meteor.user().role + " | counselorSpecific: " + JSON.stringify(Meteor.user().counselorSpecific) + " | sessionRemaining: " + Meteor.user().sessionRemaining + " | counselor: " + Meteor.user().counselor;
            return _val;
        } else {
            return"NOT LOGGED IN";
        }
    };
}

And the HTML:

<body><divstyle="padding:10px;">
        {{loginButtons}}
    </div>

    {{> home}}
</body><templatename="home"><h1>User Details</h1>
    {{> userDetails}}
</template><templatename="userDetails">
   DUMP:
   {{userDump}}
</template>

Post a Comment for "How Do You Conditionally Send Data To The Client In Meteor?"