0

In the html of the component I have the following:

<ion-card *ngFor="let recipe of recipeListRef$ | async">
....
<button *ngIf="isExistingFavorite(recipe)">
....
</ion-card>

that method searches through the favorites array:

isExistingFavorite(recipe: Recipe) {
for(let f of this.favorites){
  if(f.title === recipe.title){
    return true;
  }
}
return false;
}

the favorites array is loaded in the constructor:

favorites: Recipe[];

constructor() {
  this.favoritesService.getFavorites()
    .subscribe(
      favorites => {
        this.favorites = favorites;
      }
    );
}

the issue is that the page loads before the 'favorites' array is populated, and this results in the page crashing due to the array being null.

I am looking for a way to populate the array first, and then load the html.

~UPDATE~ I have added the following in the component but in the case that the user is authenticated, it always rejects although none of the console.logs print out at all...

ionViewCanEnter() {
return new Promise((resolve, reject) => {
  if(this.authService.isAuthenticated()) {
    this.favoritesService.getFavorites()
      .subscribe(
        favorites => {
          console.log('got the data', favorites);
          this.favorites = favorites;
          resolve(favorites);
        },
        error => {
          console.log('failed to get data', error);
          reject(error);
        }
      );
  }else{
    resolve(true);
  }
});

here is the getFavorites() service component:

  favoriteListRef$: FirebaseListObservable<Recipe[]>;

constructor(private database: AngularFireDatabase) {
  this.favoriteListRef$ = this.database.list('myUrl', { preserveSnapshot: true});
}
}

getFavorites() {
  return this.favoriteListRef$;
}
2
  • just set it to empty in the beginning. favorites: Recipe[]=[]; Commented Oct 8, 2017 at 7:22
  • @suraj yes, but that only returns an empty array, which results in the isExistingFavorite() method to return false every time. Commented Oct 8, 2017 at 12:55

1 Answer 1

1

If a variable that is expected to be defined is undefined at some point, it should either have initial value:

favorites: Recipe[] = [];

Or additional check should be performed in places where it is expected to be defined:

isExistingFavorite(recipe: Recipe) {
  if (!this.favorites)
    return;

  for(let f of this.favorites){
  ...

The idiomatic way to solve this in Angular is to move getFavorites request to route resolver, so the array is already available as activatedRoute.snapshot.data['favorites'] when route component is instantiated.

The alternative to route resolver in Ionic is ionViewCanEnter hook.

A way that will work for both raw Angular and Ionic is to provide additional guard to the template:

<ng-container *ngIf="favorites">
  <ion-card ...>...</ion-card>
</ng-container>
Sign up to request clarification or add additional context in comments.

4 Comments

I believe ionViewCanEnter is what I'm looking for. I have incorporated it in my code but having an issue. Please check my edit in the original post.
If it rejects, you can chain the promise with catch and check what's the rejection and then track it back. But from the code you've posted, I don't see what can be wrong here.
it is saying favoriteListRef$ is undefined
That sounds strange, because in your code it's defined. Any way, that's something, I guess. Also, the errors in promise construction function should be caught with try..catch, in addition to catch().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.