Reputation:
I am sending an HTTP request to a backend and receiving the data. I am passing the data through an observable stream and directly subscribing it in my HTML template using async pipe. However, I am having an issue. Since, I want to send multiple requests on the click of the button again and again, I want the observable to keep adding the new values to the data stream instead of entirely replacing the previous ones. How can I do that?
Here's my code:
TS
productsData$ = this.productService.getProduct(this.payload);
loadMore()
{
....
this.productsData$ = this.productService.getProduct(updatedpayload);
}
HTML
<div class = "grid" *ngIf="productsData$ | async as productsData">
<div class="p-col-12 p-md-6 p-lg-3" *ngFor = "let pData of productsData; let i = index">
...
How can I retain the previous values in the observable stream while sending an HTTP request and adding the new ones to the existing?
Upvotes: 2
Views: 4049
Reputation: 1334
I would recommend to use BehaviorSubject
for this problem but a bit differently than the accepted answer proposed.
First of all I would put all the data handling logic into the service and not the component consuming it.
private productsDataSubject: BehaviorSubject<any> = new BehaviorSubject([]);
public productsData$ = this.productsDataSubject.asObservable();
getProduct(payload: any) {
return this.httpClient.get('xxx').pipe(
tap((product) => {
this.productsDataSubject.next([...this.productsDataSubject.getValue(), product]);
}),
)
}
In the component we then only have this
public productsData$ = this.productService.productsData$;
loadMore(){
// plain http observable doesn't have to be unsubscribed so it's ok to leave it here
this.productService.getProduct(this.payload).subscribe();
}
It would be better for reusing it and combining with other data streams.
Upvotes: 0
Reputation: 190
Try merge from rxjs
productsData$ = this.productService.getProduct(this.payload);
loadMore(){
....
this.productsData$ = merge(this.productsData$, this.productService.getProduct(updatedpayload));
}
Upvotes: 1
Reputation: 40677
I agree with the comments. You can create a cache array and leverage that to return the previous values as well.
private readonly previousProductsData = [];
readonly buttonTrigger$ = new BehaviourSubject('');
productsData$ = this.buttonTrigger$.pipe(
switchMap(()=> this.productService.getProduct(this.payload)),
tap((product)=> {
this.previousProductsData.push(product)
}),
map(()=> this.previousProductsData)
);
and the button click could look like:
loadMore()
{
....
this.productService.buttonTrigger$.next('');
}
Upvotes: 4
Reputation: 331
push the response to an array and use that to display
this.productsData$ = this.productService.getProduct(updatedpayload);
this.productArray.push(this.productsData$);
And display productArray
Upvotes: 0