2
votes

I am currently using Meteor together with Ionic via the meteor-rxjs package. Recently I made a Component for a Login toolbar. It is supposed to display my username and Avatar if I am logged in and shows a Login button if I am currently not logged in.

The component is connected with an account service that stores a user$ Observable containing the user information so it should react whenever my login-status changes.

It doesn't react as expected though. If I am logged out and try to log in, the view doesn't change. However, if I reload the page while being logged in I can logout and login and the view always reacts to the change of my status.

AccountService:

export class AccountService {

  user$: Observable<Meteor.User>;

  constructor() {

    this.user$ = Users.find({_id: Meteor.userId()}).pipe(zoneOperator());

  }
}

Note: zoneOperator() is a function from meteor-rxjs that calls ngZone each time when new data arrives at the Mongo cursor observable.

Component

  <ion-toolbar>
    <ion-buttons *ngIf="(account.user$ | async) as users" slot="end">

      <ion-item *ngIf="users.length > 0 ; else loginTP">
        <ion-avatar class="ion-margin-end">
          <img src="{{users[0].avatar}}">
        </ion-avatar>
        <ion-label>{{users[0].username}}</ion-label>

        <ion-button (click)="logout()">
          <ion-icon name="log-out-outline"></ion-icon>
        </ion-button>
      </ion-item>

      <ng-template #loginTP>
        <ion-button (click)="login()">
          <ion-icon slot="start" name="log-in-outline"></ion-icon>
          Login
        </ion-button>
      </ng-template>

    </ion-buttons>
  </ion-toolbar>

The problem is that the view doesn't update if I am not logged in initially. It only works as expected when I am logged in at the beginning. My assumption is that somehow the initial state isn't reactive.

Meteor.userId() is null if I am not logged in.

But logging this.user$ within the AccountService shows that Users.find({_id: null}) still returns an Observable.

Any help would be appreciated. :)

1
you need to unsubscribe your observer on ngOnDestroy method, for more help check this link medium.com/angular-in-depth/…rajanbhadauria

1 Answers

0
votes

I found a solution using Meteors built in dependency tracking system: Tracker This updates the view correctly even if I am logged out initially. Here is the final code:

Service

export class AccountService {

  user$: Observable<Meteor.User>;

  constructor() {
    const ctrl = this;

    Tracker.autorun(() => {
      Users.find({_id: Meteor.userId()})
          .pipe(take(1), zoneOperator())
          .subscribe(user => {
        if (user) {
          ctrl.user$ = user[0];
        } else {
          ctrl.user$ = EMPTY;
        }
      });
    });
  }

}

Component

  <ion-toolbar>
    <ion-buttons slot="end">
      <ion-item *ngIf="account.user$ as user ; else loginTP">
        <ion-avatar class="ion-margin-end">
          <img src="{{user.avatar}}">
        </ion-avatar>
        <ion-label>{{user.username}}</ion-label>

        <ion-button (click)="logout()">
          <ion-icon name="log-out-outline"></ion-icon>
        </ion-button>
      </ion-item>

      <ng-template #loginTP>
        <ion-button (click)="login()">
          <ion-icon slot="start" name="log-in-outline"></ion-icon>
          Login
        </ion-button>
      </ng-template>

    </ion-buttons>
  </ion-toolbar>