Angular2-meteor - переменная undefined после find() с сортировкой в ​​функции подписки

Я новичок в Meteor и пакете angular2-meteor, и я пытаюсь научиться использовать их, следуя хорошо сделанному учебному пособию "Социально", найденному здесь: Социально турориальный.

Экспериментируя с тем, что я видел там о функциях публикации / подписки, я обнаружил проблему, которую не знаю, как ее решить. Чтобы было понятно, я сделал очень простой проект с такой структурой:

/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", чтобы они поменялись местами, приложение перестанет работать так, как должно, и консоль браузера скажет:

ИСКЛЮЧЕНИЕ: TypeError: l_test0 не определен в [{{test._id}} в Социально @3:15]

Например, если у меня есть:

  • id: 1 - число: 6

  • id: 2 - число: 5

  • id: 3 - число: 4

и затем я пытаюсь обновить запись с помощью "num" 4 вместо "num" на 7, новые результаты должны быть:

  • id: 3 - число: 7
  • id: 1 - число: 6
  • id: 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}

2 ответа

Решение

ОБНОВЛЕНИЕ: проверьте здесь, ошибка исправлена, так как angular2-meteor@0.5.1! Ты можешь использовать Mongo.Cursor сейчас.

Проблема в том, что при использовании sort и список меняется, вы не можете использовать tests:Mongo.Cursor<Test> с *ngFor прямо сейчас. *ngFor не поддерживается Mongo.Cursor отлично в angular2-метеоре. Так что вам нужно использовать чистый Angular 2 way.

Тебе нужно 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

Я надеюсь, что есть лучший ответ, но у меня та же проблема, и я пробовал несколько вещей.

Я обнаружил, что если я добавлю наблюдателя к курсору внутри автозапуска, то все будет работать так, как ожидается:

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>

Тем не менее, это показывает, что может быть основной проблемой, на которую отвечает ответ Хунбо.

Другие вопросы по тегам