I'm new to Meteor and the angular2-meteor package and I'm trying to learn how to use them following the well made "Socially" app tutorial found here: Socially turorial.
While experimenting with what I have seen there about the Publish/Subscribe functions, I've found a problem which I don't know how to solve. To make it clear I've made a very simple project with this structure:
/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 - is just publishing everything
import {Tests} from 'collections/tests';
Meteor.publish('tests', function() {
return Tests.find();
});
/client/app.ts - subscribe sorting the results
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 - a simple ngFor, showing the results
<div>
<ul>
<li *ngFor="#test of tests">
<p>{{test._id}}</p>
<p>{{test.num}}</p>
</li>
</ul>
</div>
If I insert or remove entries from the database using the Mongo console, everything is working fine. The same thing if I update an existing entry without changing their order. However, if I try to update one of the already existing entries putting a higher number in its "num" field making them switch positions, the app stops working as it should and the browser console says:
EXCEPTION: TypeError: l_test0 is undefined in [{{test._id}} in Socially@3:15]
For example if I have :
id: 1 - num: 6
id: 2 - num: 5
id: 3 - num: 4
and then I try to update the entry with "num" 4 putting "num" to 7 instead, the new results should be:
which is giving me the said error.
It might be stupid, but since I'm a real newbie with meteor I can't seem to understand what's wrong and I would be glad if you could give me a hand.
Thank you in advance.
EDIT: In my original project I used a form to add/remove entries directly from the page. In this test project I removed all the unnecessary things to keep it as simple as possible and used the mongo console:
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}})
If I then do:
db.tests.find()
it shows:
{ "_id" : 1, "num" : 6 }
{ "_id" : 2, "num" : 5 }
{ "_id" : 3, "num" : 7 }
UPDATE: Check here, the bug is fixed since angular2-meteor@0.5.1! You can use Mongo.Cursor
now.
The problem is that when using sort
and the list changes, you cannot use tests:Mongo.Cursor<Test>
with *ngFor
right now. *ngFor
does not support Mongo.Cursor
perfectly in angular2-meteor. So you need use pure Angular 2 way.
You need fetch()
first and use Array<Test>
, otherwise it will show this error when the list or order of list changes:
Cannot read property 'XXX' of undefined
So the final working code is like this:
<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);
});
}
Refer to issue on github