4

我是 Meteor 和 angular2-meteor 包的新手,我正在尝试按照此处找到的精心制作的“社交”应用程序教程学习如何使用它们:Socially turorial

在尝试我在那里看到的关于发布/订阅功能的内容时,我发现了一个我不知道如何解决的问题。为了清楚起见,我用这个结构做了一个非常简单的项目:

/typings/test.d.ts

interface Test {    
    _id?: string;
    num: number;
}

/collections/tests.ts

export var Tests = new Mongo.Collection<Test>('tests');

/server/main.ts

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

/client/app.html - 一个简单的 ngFor,显示结果

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

如果我使用 Mongo 控制台从数据库中插入或删除条目,一切正常。如果我在不更改其顺序的情况下更新现有条目,也会发生同样的事情。但是,如果我尝试更新已经存在的条目之一,在其“num”字段中放置更高的数字,使它们切换位置,则应用程序将停止正常工作,并且浏览器控制台会显示:

例外:类型错误:l_test0 在 Socially@3:15 的 [{{test._id}} 中未定义]

例如,如果我有:

  • 编号:1 - 编号:6

  • 编号:2 - 编号:5

  • 编号:3 - 编号:4

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

  • 编号:3 - 编号:7
  • 编号:1 - 编号:6
  • 编号:2 - 编号:5

这给了我上述错误。

这可能很愚蠢,但由于我是一个真正的流星新手,我似乎无法理解出了什么问题,如果你能帮我一把,我会很高兴。

先感谢您。

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

db.tests.insert({_id: 1, num: 6})

db.tests.insert({_id: 2, num: 5})

db.tests.insert({_id: 3, num: 4})

db.tests.update({_id: 3}, {$set: {num: 7}})

如果我这样做:

db.tests.find()

表明:

{ "_id" : 1, "num" : 6 }

{ "_id" : 2, "num" : 5 }

{ "_id" : 3, "num" : 7 }

4

2 回答 2

2

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

问题是,当使用sort并且列表发生变化时,您现在不能使用tests:Mongo.Cursor<Test>with *ngFor*ngFor不完全支持Mongo.Cursorangular2-meteor。所以你需要使用纯 Angular 2 方式。

您需要fetch()先使用Array<Test>,否则当列表或列表顺序发生变化时会显示此错误:

无法读取未定义的属性“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);
    });
}

参考github上的issue

于 2016-03-14T05:52:44.750 回答
1

我希望那里有更好的答案,但我有同样的问题并且一直在尝试一些事情。

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

this.tests.observeChanges({changed: () => {
    this.tests = Tests.find({}, {sort: {num: -1}});
}})

根据我一直在阅读的所有内容,这似乎不是必需的,但它确实对我有用。

为了防止它试图在短暂结束的光标中显示文档undefined,我添加了一个ngIf

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

编辑

我一直有一些很难确定的问题。在 ngFor 和 ngIf 上阅读此问题后,我猜这是因为我在同一个元素上有 ngFor 和 ngIf,这显然不受支持。相反,他们建议将 ngIf 移至封闭<template>标记:

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

然而,这揭示了可能是根本问题,洪波的回答解决了这个问题。

于 2016-02-25T15:01:55.230 回答