shAkur
shAkur

Reputation: 1002

Angular's ngIf showing else template before evaluating condition

I'm checking if there are any elements in array before showing them. If there aren't, a "not available" message should be displayed.

Class:

public lists = [];
public isLoading: boolean = false;

ngOnInit() {
  this.getLists()
}

getLists() {
  this.isLoading = true;
  this.list.getShoppingLists().subscribe(data => {
    this.isLoading = false;
    this.lists = data.data;
  });
}

Template:

<mat-spinner *ngIf="isLoading" class="mx-auto"></mat-spinner>

<div *ngIf="lists.length > 0; then withLists else withoutLists"></div>

<ng-template #withLists>
  <div *ngFor="let list of lists">
      <p>{{list.title}}</p>
  </div>
</ng-template>

<ng-template #withoutLists>
 <p>No lists available</p>
</ng-template>

The problem I have is that "not available" message shows in template whilst data is being returned from the API and it shouldn't. Any ideas why this is happening and how should I address this issue?

Upvotes: 1

Views: 1190

Answers (2)

Mehdi Anis
Mehdi Anis

Reputation: 66

the callback in subscribe is asynchonous, that means the list is empty while the data is loading, therefore you need to wait for the completion of the loading. you can solve this either by making:

<div *ngIf="isLoading || lists.length > 0; then withLists else withoutLists"></div>

or wrapping everything like this :

<div *ngIf="isLoading">
    <div *ngIf="lists.length > 0; then withLists else withoutLists"></div>

    <ng-template #withLists>
        <div *ngFor="let list of lists">
            <p>{{list.title}}</p>
        </div>
    </ng-template>

    <ng-template #withoutLists>
        <p>No lists available</p>
    </ng-template>
</div>

Upvotes: 0

peinearydevelopment
peinearydevelopment

Reputation: 11474

This is happening because your if clause is based on the length of the lists array which is given an initial value of an empty array.

Updating the logic to include isLoading would help for this specific scenario.

<div *ngIf="isLoading || lists.length > 0; then withLists else withoutLists"></div>

As per the comments below, a better approach might be to do something more like:

<ng-component *ngIf="!isLoading">
   <div *ngIf="lists.length > 0; then withLists else withoutLists"></div>
</ng-component>

This way, the intent of the code would be more clear. If it is still loading, don't show anything. Else show the diff with the if/else logic based on the length of lists.

Upvotes: 3

Related Questions