Search code examples
mongodbmeteorangularangular2-meteor

Angular2-meteor - Variable undefined after a find() with sort in a subscribe function


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:

  • id: 3 - num: 7
  • id: 1 - num: 6
  • id: 2 - num: 5

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 }


Solution

  • UPDATE: Check here, the bug is fixed since [email protected]! 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