Search code examples
meteortypescriptangularangular2-meteor

Using pipe in *ngFor, the page sometimes updates, sometimes not


I am using angular2-meteor, I already use pure: false. But the pipe sometimes run, sometimes not. See my comments in the code for details of the problem.

Thanks

<div *ngFor="#user of (users|orderByStatus)">
    {{user.status.online}}
</div>


users:Mongo.Cursor<Meteor.User>;
ngOnInit()
{
    this.subscribe('users', () => {
        this.autorun(() => {
            this.users = Meteor.users.find();
        });
    }, true);
}

import {Pipe} from 'angular2/core';

@Pipe({
    name: 'orderByStatus',
    pure: false
})
export class OrderByStatusPipe {
    transform(usersCursor:Mongo.Cursor<Meteor.User>):Array<Meteor.User> {
        console.log("OrderByStatusPipe runs");

        // (1) If I only do these two lines, the change of other users' status can show on the screen immediately. 
        // let users = usersCursor.fetch();
        // return users;

        // (2) If sort users by status, the page sometimes updates, sometimes not when user status change.
        //  If not update automatically, I click that part of screen, it will update then.
        let users:Array<Meteor.User> = usersCursor.fetch();
        users.sort((a, b) => {
            return (a.status.online === b.status.online) ? 0 : (a.status.online ? -1 : 1);
        });
        return users;
    }
}

Solution

  • UPDATE: The bug seems fixed.

    I think the problem is related with angular2-meteor.

    At last I found a working way using sort in when you try to get data from Mongo. So not using sort pipe any more.

    But you cannot use users:Mongo.Cursor<Meteor.User> with *ngFor, need fetch() first and use Array<Meteor.User>, otherwise it will show this error when the order of list changes:

    Cannot read property 'status' of undefined

    But then the list won't update automatically in UI. So you need use NgZone.

    So the final working code is like this:

    <div *ngFor="#user of users)">
        {{user.status.online}}
    </div>
    
    
    users:Array<Meteor.User>;  // here cannot use users:Mongo.Cursor<Meteor.User>
    constructor(private _ngZone:NgZone) {}
    ngOnInit()
    {
        this.subscribe('users', () => {
            this.autorun(() => {
                this._ngZone.run(() => {
                    this.users = Meteor.users.find().fetch();
                });
            });
        }, true);
    }