简体   繁体   English

您如何有条件地将数据发送到Meteor中的客户端?

[英]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 the data they require is different). 我有两种用户类型,根据用户的类型,它们在客户端上的接口(因此它们所需的数据是不同的)。

Lets say users are of type counselor or student . 让我们说用户是型counselorstudent Every user document has something like role: 'counselor' or role: 'student' . 每个用户文档都有类似role: 'counselor'role: 'student'

Students have student specific information like sessionsRemaining and counselor , and counselors have things like pricePerSession , etc. 学生有学生特定的信息,如sessionsRemainingcounselor ,辅导员有像pricePerSession等。

How would I make sure that Meteor.user() on the client side has the information I need, and none extra? 我如何确保客户端的Meteor.user()具有我需要的信息,而且没有额外的信息? 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. 如果我以学生Meteor.user()登录, Meteor.user()应该包括sessionsRemainingcounselor ,但如果我以辅导员的身份登录,则不会。 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. 使用fields选项仅返回Mongo查询所需的字段。

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. 订阅可以在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. 因此,这种方法的优点在于,向客户端提供额外字段的发布功能与Meteor的幕后发布功能一起工作,该功能发送基本字段,如用户的电子邮件地址和配置文件。 On the client, the document in the Meteor.users collection will be the union of the two sets of fields. 在客户端上, Meteor.users集合中的文档将是两组字段的并集。

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. 默认情况下,Meteor用户只发布其基本信息,因此您必须使用Meteor.publish手动将这些字段添加到客户端。 Thankfully, the Meteor docs on publish have an example that shows you how to do this: 值得庆幸的是, 发布Meteor文档有一个示例,向您展示如何执行此操作:

// 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");

Because Meteor.users is a collection like any other Meteor collection, you can actually refine its publicized content like any other Meteor collection: 因为Meteor.users是一个像任何其他Meteor集合一样的集合,你实际上可以像任何其他Meteor集合一样优化其公开内容:

Meteor.publish("users", function () {
    //this.userId is available to reference the logged in user 
    //inside publish functions
    var _role = Meteor.users.findOne({_id: this.userId}).role;
    switch(_role) {
        case "counselor":
            return Meteor.users.find({}, {fields: { sessionRemaining: 0, counselor: 0 }});
        default: //student
            return Meteor.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. 因此, Meteor.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 functions
        var _role = Meteor.users.findOne({ _id: this.userId }).role;
        console.log("userid: " + this.userId);
        console.log("getting role: " + _role);
        switch (_role) {
            case "counselor":
                return Meteor.users.find({}, { fields: { sessionRemaining: 0, counselor: 0 } });
            default: //student
                return Meteor.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: 和HTML:

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

    {{> home}}
</body>

<template name="home">
    <h1>User Details</h1>
    {{> userDetails}}
</template>

<template name="userDetails">
   DUMP:
   {{userDump}}
</template>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM