流星 - 在列表对象中呈现所有者的名称
Meteor - rendering the name of the owner in a list objects
当我尝试查找对象的所有者时,我收到一个找不到对象错误我正在尝试渲染。我正在循环浏览一组视频剪辑,这些剪辑可以由用户更新或管理。当我登录时,代码工作正常,但是当我尝试使用它并注销时,我得到"排队任务中的异常:类型错误:无法读取 Object.Template.video_info.creatorName 处未定义的属性'_id' "
我试图通过这样做来调试它:
console.log(this.owner);
var owner = Meteor.users.findOne(this.owner);
console.log(owner);
当我检查控制台日志时,我可以看到找到了正确的用户ID,当我使用此ID手动运行Meteor.users.findOne时,我返回了一个用户对象。流星的时间有什么奇怪的地方阻止了这一点吗?
更新:如果我添加尝试...捕获到模板创建者名称函数,然后记录 2 个错误,但模板仍然呈现... ???似乎这个模板被调用了两次,一次是在它还没有准备好的时候,一次是一次。为什么会这样。
尝试示例...捕获块:
Template.video_info.creatorName = function () {
try{
var owner = Meteor.users.findOne(this.owner);
if (owner._id === Meteor.userId())
return "me";
return displayName(owner);
} catch (e){
console.log(e);
}
};
此点以下的原始损坏代码
这是我的 HTML 中:
<body>
<div>
{{> video_list}}
</div>
</body>
<template name="video_list">
<h1>Video List</h1>
{{#each videos}}
<ul>
{{> video_info}}
</ul>
{{else}}
No videos yet.
{{/each}}
<div class="footer">
<button>Like!</button>
</div>
</template>
<template name="video_info">
<li class="video-list {{maybe_selected}}">
<img src="{{image}}" />
<div>
<h3>{{title}}</h3>
<p>{{description}}</p>
<h4>{{creatorName}}</h4>
</div>
</li>
</template>
这是我的客户端.js
Meteor.subscribe("videos");
if (Meteor.isClient) {
Template.video_list.videos = function() {
return Videos.find({}, {sort: {title: 1}});
};
Template.video_list.events = {
'click button': function(){
Videos.update(Session.get('session_video'),{$inc: {likes: 1}});
}
}
Template.video_info.maybe_selected = function() {
return Session.equals('session_video', this._id) ? "selected" : "";
}
Template.video_info.events = {
'click': function(){
Session.set('session_video', this._id);
}
}
Template.video_info.creatorName = function () {
var owner = Meteor.users.findOne(this.owner);
if (owner._id === Meteor.userId())
return "me";
return displayName(owner);
};
}
if (Meteor.isServer) {
Meteor.startup(function () {
// code to run on server at startup
});
}
这是我的模型.js
Videos = new Meteor.Collection("videos");
Videos.allow({
insert: function (userId, video) {
return false; // no cowboy inserts -- use createParty method
},
update: function (userId, video, fields, modifier) {
if (userId !== video.owner)
return false; // not the owner
var allowed = ["title", "description", "videoid", "image", "start"];
if (_.difference(fields, allowed).length)
return false; // tried to write to forbidden field
// A good improvement would be to validate the type of the new
// value of the field (and if a string, the length.) In the
// future Meteor will have a schema system to makes that easier.
return true;
},
remove: function (userId, video) {
// You can only remove parties that you created and nobody is going to.
return video.owner === userId; //&& attending(video) === 0;
}
});
var NonEmptyString = Match.Where(function (x) {
check(x, String);
return x.length !== 0;
});
var NonEmptyNumber = Match.Where(function (x) {
check(x, Number);
return x.length !== 0;
});
createVideo = function (options) {
var id = Random.id();
Meteor.call('createVideo', _.extend({ _id: id }, options));
return id;
};
Meteor.methods({
// options should include: title, description, x, y, public
createVideo: function (options) {
check(options, {
title: NonEmptyString,
description: NonEmptyString,
videoid: NonEmptyString,
image:NonEmptyString,
start: NonEmptyNumber,
_id: Match.Optional(NonEmptyString)
});
if (options.title.length > 100)
throw new Meteor.Error(413, "Title too long");
if (options.description.length > 1000)
throw new Meteor.Error(413, "Description too long");
if (! this.userId)
throw new Meteor.Error(403, "You must be logged in");
var id = options._id || Random.id();
Videos.insert({
_id: id,
owner: this.userId,
videoid: options.videoid,
image: options.image,
start: options.start,
title: options.title,
description: options.description,
public: !! options.public,
invited: [],
rsvps: []
});
return id;
},
});
///////////////////////////////////////////////////////////////////////////////
// Users
displayName = function (user) {
if (user.profile && user.profile.name)
return user.profile.name;
return user.emails[0].address;
};
var contactEmail = function (user) {
if (user.emails && user.emails.length)
return user.emails[0].address;
if (user.services && user.services.facebook && user.services.facebook.email)
return user.services.facebook.email;
return null;
};
我已经找到了这个问题的解决方案。在阅读了Meteor中的缓存工作后,我发现了订阅模式以及这与meteors minimongo http://docs.meteor.com/#dataandsecurity 的关系。失败然后成功的原因是,在第一次加载时,数据仍然缓存在minimongo中。我目前正在检查帐户登录服务配置为检查用户数据是否已加载。我目前正在使用它,因为我找不到订阅 Metor 用户服务的方法,但我的猜测是帐户登录服务将依赖于 Metor 用户集合。我当前的解决方案如下所示:
if(Accounts.loginServicesConfigured()){
var owner = Meteor.users.findOne(this.owner);
if (owner._id === Meteor.userId())
return "me";
return displayName(owner);
}
目前,这似乎工作正常。我仍在深入研究如何订阅此用户服务。我在为此寻找解决方案时发现了几个非常有用的参考
- https://github.com/oortcloud/unofficial-meteor-faq
- http://psychopyko.com/cool-stuff/meteor-6-simple-tips/
- https://groups.google.com/forum/#!topic/meteor-talk/QKXe7qfBfqg
注销时,应用程序可能未将用户 ID 发布到客户端。可以尝试在服务器上调用 find 方法并返回用户。或者使用不同的键进行查询/
- 要求输入在数据列表中
- 从javascript创建一个列表
- 如何使用jQuery选择下拉列表的值
- 将输入字段中的文本提交到我的数据库,同时将其添加到我的列表中
- 将jsp文件下拉列表中的选定项分配给一个java变量(比如String selection)
- Javascript按钮下拉列表
- 如何使用json将对象列表从java转换为javascript
- 区分JSON中的矩阵和列表列表
- jQuery表单添加不适用于下拉列表
- 用每小时的差值填充数组/列表-从下拉列表中给定两个时间值
- 接受不在列表中的值-引导组合框
- 禁用jQuery中的下拉列表
- 从HTTPGET返回一个自定义对象列表,以便在Angular 2应用程序中使用
- 如何在javascript中迭代数字列表
- 如何在按钮中显示下拉列表中选定的元素
- 为什么HTML5拖放的目标是孩子?(可排序列表)
- 鼠标悬停事件影响列表中所有行中的按钮,而不仅仅是特定按钮
- 使用图像数组列表的simplegallary.js显示适合桌面屏幕的图像
- 所有者下拉列表未过滤故事纸板
- 流星 - 在列表对象中呈现所有者的名称