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>
Тем не менее, это показывает, что может быть основной проблемой, на которую отвечает ответ Хунбо.