I have an Angular 6 app with the following requirements:

1. Get data from a web service.
2. Load the data when the page is displayed.
3. Reload the data when the user requests a reload by through some UI, like a button.
4. Show a spinner while loading data in the header of the page. That is, not in the same place where the data is going to be displayed. Which means I cannot use ngIf with ; else #loading.

I have the following (simplified) code that is actually working. I also have a live code sample. However I wonder if this is the canonical way to do it. Especially as I a am new to RxJS. Other improvements or suggestions are also welcome.

Some things I am not sure of:

• Using the refresh Subject to do load/reload.
• Setting the loading member within RxJS operators (side effects).

The component:

@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
items$: Observable<any>; // Some items loading: boolean = true; // Turn spinner on and off constructor (private http: HttpClient) { } ngOnInit() { this.refresh = new Subject(); this.items$ = this.refresh.asObservable()
.pipe(
startWith('onInit'), // Emit value to force load on page load; actual value does not matter
flatMap(_ => this.http.get<any>('https://swapi.co/api/people/')), // Get some items
delay(1000), // Delay to let our spinner shine
map(data => data.results), // Map data
);
}

onRefresh() {

<div class="header">
<div *ngIf="items$| async as items"> <ul> <li *ngFor="let item of items"> {{item.name}} </li> </ul> </div> </div>  • In this context, it is better to use switchMap than flatMap. – rveerd Nov 6 '19 at 13:34 • This breaks when an error occurs. The items$ observable completes (with an error) and calling refresh.next() no longer has any effect. – rveerd Nov 6 '19 at 13:35