Search code examples
meteortypescriptangularangular2-meteor

UI not update (have to click somewhere) & router not work in Angular2-Meteor


I cannot update the UI immediately after subscribing the data from database, I have to click somewhere

Also if I use the router to go to another page, it does not work

@Component({
  selector: 'foo-component',
  template: `
    {{foo}}
  `
})
export class FooComponent extends MeteorComponent {
  foo: string ;

  constructor() {
    super();

    this.subscribe('messages', () => {
      // I cannot change foo value immediately, I have to click somewhere
      this.foo = 'foo';

      // Also if I use the router to go to another page, it does not work
      // this.router.navigate(['Home']);
    });
  }
}

How to solve this?


Solution

  • Note the new angular2-meteor version autoBind is set to true by default. So you probably won't meet this issue again.

    But you still need use NgZone in Accounts.changePassword or other similar Accounts.foo() functions.


    This problem is because that part of code run out of Angular 2 zone, you need run it inside of zone to update UI immediately or use router to go to another page.

    Where do these problems usually happen?

    Most time you don't do this. So when do you need this? Usually in callback of Meteor functions:

       this.autorun(() => {
         // here you need
       });
    
       this.subscribe('messages', () => {
         // here you need
       });
    
       this.call('newMessage', (error, result) => {
         // here you need
       });
    
       Accounts.changePassword(currentPassword, newPassword, error => {
         // here you need
       });
    

    How to solve?

    Take

     this.call('newMessage', (error, result) => {
       this.router.navigate(['Home']);
     });
    

    for example, you need change to:

    import { NgZone } from '@angular/core';
    
    constructor(private zone: NgZone) {}
    
    this.call('newMessage', (error, result) => {
      this.zone.run(() => {
        this.router.navigate(['Home']);
      });
    });
    

    Is there a clean way?

    Luckily, Angular2-Meteor helps you do this dirty work.

    Check Angular2-Meteor API document, there is an autoBind parameter for this.subscribe and this.autorun.

    So now you don't need use this.zone.run, instead you can just add a true:

       this.autorun(() => {
         // your code
       }, true);
    
       this.subscribe('messages', () => {
         // your code
       }, true);