Mongodb Angular2 meteor-订阅函数中带有sort的find()后未定义的变量

Mongodb Angular2 meteor-订阅函数中带有sort的find()后未定义的变量,mongodb,meteor,angular,angular2-meteor,Mongodb,Meteor,Angular,Angular2 Meteor,我是Meteor和angular2 Meteor软件包的新手,我正在努力学习如何使用它们,下面是制作精良的“社交”应用程序教程: 在试验发布/订阅函数时,我发现了一个我不知道如何解决的问题。为了明确起见,我用这种结构做了一个非常简单的项目: /typings/test.d.ts interface Test { _id?: string; num: number; } export var Tests = new Mongo.Collection<Test>

我是Meteor和angular2 Meteor软件包的新手,我正在努力学习如何使用它们,下面是制作精良的“社交”应用程序教程:

在试验发布/订阅函数时,我发现了一个我不知道如何解决的问题。为了明确起见,我用这种结构做了一个非常简单的项目:

/typings/test.d.ts

interface Test {    
    _id?: string;
    num: number;
}
export var Tests = new Mongo.Collection<Test>('tests');
import './tests';
/collections/tests.ts

interface Test {    
    _id?: string;
    num: number;
}
export var Tests = new Mongo.Collection<Test>('tests');
import './tests';
/server/test.ts-正在发布所有内容

import {Tests} from 'collections/tests'; 

Meteor.publish('tests', function() {
    return Tests.find();
});
/client/app.ts-订阅结果排序

import {Component, View} from 'angular2/core';

import {bootstrap} from 'angular2-meteor';

import {MeteorComponent} from 'angular2-meteor';

import {Tests} from 'collections/tests';

@Component({
    selector: 'app'
})

@View({
    templateUrl: 'client/app.html'
})

class Socially extends MeteorComponent {
    tests: Mongo.Cursor<Test>;

    constructor(){
        super();      
        this.subscribe('tests', () => {
            this.tests = Tests.find({}, {sort: {num: -1}});
        }, true);
    }
}

bootstrap(Socially);
<div>
    <ul>
        <li *ngFor="#test of tests">
            <p>{{test._id}}</p>
            <p>{{test.num}}</p>
        </li>
    </ul>
</div>
从'angular2/core'导入{Component,View};
从“angular2 meteor”导入{bootstrap};
从“angular2 meteor”导入{MeteoComponent};
从“集合/测试”导入{Tests};
@组成部分({
选择器:“应用程序”
})
@看法({
templateUrl:'client/app.html'
})
类对组件进行社会扩展{
测试:Mongo.Cursor;
构造函数(){
超级();
this.subscribe('tests',()=>{
this.tests=tests.find({},{sort:{num:-1});
},对);
}
}
引导(社会);
/client/app.html-一个简单的ngFor,显示结果

import {Component, View} from 'angular2/core';

import {bootstrap} from 'angular2-meteor';

import {MeteorComponent} from 'angular2-meteor';

import {Tests} from 'collections/tests';

@Component({
    selector: 'app'
})

@View({
    templateUrl: 'client/app.html'
})

class Socially extends MeteorComponent {
    tests: Mongo.Cursor<Test>;

    constructor(){
        super();      
        this.subscribe('tests', () => {
            this.tests = Tests.find({}, {sort: {num: -1}});
        }, true);
    }
}

bootstrap(Socially);
<div>
    <ul>
        <li *ngFor="#test of tests">
            <p>{{test._id}}</p>
            <p>{{test.num}}</p>
        </li>
    </ul>
</div>

    {{test.\u id}}

    {{test.num}

如果我使用Mongo控制台从数据库中插入或删除条目,一切正常。如果我更新一个现有条目而不更改其顺序,也是一样的。但是,如果我尝试更新其中一个已存在的条目,在其“num”字段中添加更高的数字,使其切换位置,则应用程序将停止正常工作,浏览器控制台会显示:

异常:TypeError:l_test0在中的[{test.\u id}}中未定义Socially@3:15]

例如,如果我有:

  • 编号:1-编号:6

  • id:2-数量:5

  • id:3-数量:4

然后我尝试用“num”4更新条目,将“num”改为7,新结果应该是:

  • 编号:3-编号:7
  • 编号:1-编号:6
  • id:2-数量:5
这就是我所说的错误

这可能是愚蠢的,但因为我是一个真正的流星新手,我似乎不明白什么是错的,如果你能帮我一把,我会很高兴

先谢谢你

编辑: 在我最初的项目中,我使用表单直接从页面添加/删除条目。在这个测试项目中,我删除了所有不必要的东西,使其尽可能简单,并使用了mongo控制台:

insert({u id:1,num:6})

insert({u id:2,num:5})

insert({u id:3,num:4})

update({u id:3},{$set:{num:7})

如果我这样做:

db.tests.find()

它表明:

{u id:1,“num:6}

{u id:2,“num:5}

{u id:3,“num:7}


我希望有一个更好的答案,但我也有同样的问题,我一直在尝试一些事情

我发现,如果我在自动运行中向光标添加观察者,那么一切都会按预期运行:

this.tests.observeChanges({changed: () => {
    this.tests = Tests.find({}, {sort: {num: -1}});
}})
从我所读到的一切来看,这似乎不是必要的,但对我来说确实有用

为了防止它试图在光标中显示文档,而该文档会短暂地以
未定义
结束,我添加了一个
ngIf

<li *ngFor="#test of tests" *ngIf="test">

编辑

我一直有一些难以确定的问题。在阅读之后,我猜这是因为我在同一个元素上有ngFor和ngIf,这显然是不受支持的。相反,他们建议将ngIf向上移动到一个封闭的
标签:

<template *ngIf="tests">
    <li *ngFor="#test of tests">
</template>



然而,这揭示了洪波的答案所针对的根本问题。

更新:检查,该错误自angular2以来已修复-meteor@0.5.1! 现在可以使用
Mongo.Cursor

问题是,当使用
排序
并且列表发生更改时,您现在不能将
tests:Mongo.Cursor
*ngFor
一起使用
*ngFor
在angular2 meteor中不支持
Mongo.Cursor
。所以你需要使用纯角度2路

您需要先使用
fetch()
并使用
Array
,否则当列表或列表顺序更改时,它将显示此错误:

无法读取未定义的属性“XXX”

因此,最终的工作代码如下所示:

<div *ngFor="#test of tests">

</div>

// here you cannot use tests:Mongo.Cursor<Test>
tests:Array<Test>;
constructor() {
    super();
}
ngOnInit()
{
    this.subscribe('tests', () => {
        // autorun makes sure it get latest data
        this.autorun(() => {
            // here you need fetch first
            this.tests = Tests.find({}, {sort: {num: -1}}).fetch();
        }, true);
    });
}

//这里不能使用tests:Mongo.Cursor
测试:数组;
构造函数(){
超级();
}
恩戈尼尼特()
{
this.subscribe('tests',()=>{
//自动运行确保获得最新数据
这个。自动运行(()=>{
//这是你需要先取的
this.tests=tests.find({},{sort:{num:-1}}).fetch();
},对);
});
}

请参阅github上的

以进行测试,您是否可以在模板(问号)中尝试以下语法:
{{test?{u id}}
{{test?.num}
。也许这是angular2中的一个bug,这是一个工作-around@PierreDuc谢谢你的建议。我试着按照你说的去做,错误显然已经消失了,但是现在最后更新的条目消失了,直到我再次重新加载页面(我上一个例子中的“id:3-num:7”)。嗯,你在哪里更新num值?用js还是用mongo?如果在js中,怎么做?@PierreDuc我编辑了我的原始消息来回答你的问题。现在我可以发表评论了,把这个移到这里:你不能只使用autobind参数来自动运行回调,在一个角度变化检测区域中,像这样:
this.autorun(()=>{this.tests=tests.find({},{sort:{num:-1})。fetch();},true)@Trygve该行只是确保您执行的工作运行i