So instead of subscribing directly to the this.http.get() method, define a variable to that method call, which will have type Observable<Concert[]>. Using this approach you can then define transforms on that observable.
Here's how it would look:
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
private concertsUrl = './assets/concerts.json';
concerts$: Observable<Concert[]>;
featured$: Observable<Concert[]>;
constructor (private httpService: HttpClient) {}
ngOnInit() {
this.concerts$ = this.httpService.get(this.concertsUrl)
.pipe(
tap((concerts) => console.log(concerts)),
catchError(err => console.log(err.message))
);
this.featured$ = this.concerts$.pipe(
filter(concert => concert.featured)
);
}
}
And then in your HTML, subscribe to the featured$ observable using the async pipe.
<div *ngFor="let concert of featured$ | async">
</div>
There are several advantages to this approach:
- Angular will take care of unsubscribing from observables when components are destroyed.
- You can take advantage of
ChangeDetectionStrategy.OnPush, which will enhance the performance of your app.
- You can compose the
concerts$ observable with other operators to cleanly handle more complex interactions.
Observables are an incredibly powerful mechanism for handling complex behavior and interactions. There is a steep learning curve, but the time is worth it.