Currently, I am in the process of refactoring some Angular code that previously involved subscribing to data from a service call. My goal now is to have the data returned from the service as an observable so that I can make use of the async pipe and avoid manual unsubscription at the end. My previous code snippet looked something like this:
Component.ts
people: Person[] = [];
getPeople(){
this.apiService.GetPeople().subscribe((result) => {
this.people = result;
}));
}
Subsequently, I could access the data using this.people
to manipulate it as needed.
Now, I aim to restructure my code by utilizing observables. However, if I proceed with this approach, how can I access the same data within the component without the need for subscription and subsequent unsubscription on ngOnDestroy
?
Component.ts
people$ = Observable<Person[]>;
getPeople(){
this.people$ = this.apiService.people$;
}
The corresponding code in my service layer would be:
ApiService.ts
private allPeople: BehaviorSubject<Person[]> = new BehaviorSubject<Person[]>([]);
people$ = this.allPeople.asObservable();
With people$
being converted into an observable, I can now utilize the following in my HTML:
Index.html
<div *ngIf="people$ | async">
</div>
As per my understanding, this approach handles unsubscribing automatically when required. With people$
being an observable in the component, how can I retrieve and work with the data? For instance, given an observable of cities, how do I filter them based on whether the observable people are marked with display = true
? The conventional method does not seem feasible. What would be the best way to achieve similar functionality?
Component.ts
let peopleToUse = this.people$.filter(m => m.display === true).map((filter) => {return filter.city});
this.cities$ = this.cities$.filter(m => peopleToUse.includes(m.city));
The desired outcome is to obtain a list of cities that exist in the list of people's city property where display = true
. Is there a means of achieving this without direct subscription? After all, wouldn't subscribing contradict the purpose of employing the async pipe initially?
UPDATE
In case I have two observables namely cities$
and people$
, how can I update cities$
according to changes in people$
? For example, if the user modifies one individual in people$
such that display = false
, I intend to remove that record from cities$
.
Illustration
updatePerson(person: Person){
this.apiService.updatePerson(person);
//Update this.cities$ to implement filtering once again.
let peopleToUse = this.people$.filter(m => m.display === true).map((filter) => {return filter.city});
this.cities$ = this.cities$.filter(m => peopleToUse.includes(m.city));
}