0

Now I have declaration array as:

public invoices: IInvoice[] = [];

Below it is filled by data from response:

 private load(): void {
    this.invoiceService.get().subscribe((data: any) => {
      this.invoices = data;
    });
  }

So, in template I have:

<div class="alert alert-fill-warning" *ngIf="invoices.length == 0"></div>

Problem is that while server returns data this messages is shown, because by default array is empty. How to show this message only when actually there are no data in response.

4 Answers 4

2

You can use the template syntax invoice$ | async as invoices; else loading to subscribe to an observable, but display a loading message until data is emitted. After invoices are loaded you can display the warning if the array is empty.

public invoices$: Observable<IInvoice[]>;

private load(): void {
   this.invoices$ = this.invoiceService.get();
}

<ng-container *ngIf="invoices$ | async as invoices; else loading">
    <div class="alert alert-fill-warning" *ngIf="invoices.length === 0"></div>
</ng-container>
<ng-template #loading">
    Invoices are loading...
</ng-template>

The else loading is optional. You can leave this area blank if you like until invoices are read.

Sign up to request clarification or add additional context in comments.

4 Comments

Using Observables for this is a great way to handle this issue if you understand this technique. I would accept this as my answer.
How do we check if the IInvoice[] returned are empty - i.e. length ===0. if the initial value of IInvoice is [ ]. it will never go to else and render the loading template. So basically we could either show the invoices are empty or invoices are loading.. I have a similar template for addresses: *ngIf="addressService.addresses$ | async as addresses; else loading"> <div class="col-12 col-md-10 py-2" *ngIf="addresses.length === 0">
@Irshad why do you have an initial value of []? You should use an observable that doesn't emit an initial value while it is fetching data. Sounds like you might be using a Redux store that has a default value. You should change the default to null then.
@Reactgular __ Thanks. Ya, I did notice that, after I commented here. Had to change the initial state to null rather than [ ]
2

You could make invoices optional, and check if it is defined as well as empty

public invoices?: IInvoice[];

...

*ngIf="invoices && invoices.length === 0"

Or alternatively, use a flag, like isFetchingData to indicate that a fetch from the server is in progress, and use this in your *ngIf clause.

The flag approach is probably more obvious to the reader as to what is going on, as well as avoiding extra null checks in other parts of the code if you are using strictNullChecking in your tsconfig

Comments

1

Is it necessary to set the default value to empty array? Why not set it to null and only change that upon receipt of data from the server. Then you can change your condition for the alert to check for non-null value that has a length of zero.

1 Comment

That's why I suggested changing the condition to check for non-null value with length of zero (i.e. <div class="alert alert-fill-warning" *ngIf="invoices && invoices.length == 0"></div>)
-1

This code will work:

public invoices: IInvoice[];

and

private load(): void {
this.invoiceService.get().subscribe((data: any) => {
  this.invoices = data;
});
}

Template's code is ok.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.