We have a page where there are multiple sections. Each section can have a card or a table. An observable binds data in html using async pipe. Now I need to update one of the table without refreshing whole observable.
loadPageData(Id): void {
this.sections$ = this.psService.getLoadPageData(Id).pipe(
switchMap(sections => forkJoin(
sections.map(section => this.psService.getSectionData(section.sectionID).pipe(
map(card => Object.assign({}, section, { card })),
switchMap(c => c.card.map(card => iif(() => card.cardTypeId === 3,
from(this.psService.getTable(this.tablePerodID).pipe(map(table => Object.assign({}, c, { table })))),
of(c))))
).concatAll()
))
));
}
updateTable(sectionId, tablePerodID) {
let tableData;
this.psService.getTable(tablePerodID).subscribe((data) => {
tableData = data;
});
this.sections$.forEach(sections => {
sections.forEach(section => {
if (section.sectionID === sectionId) {
section.table = sectionData;
}
});
});
}
and the HTML is like:
<div *ngFor="let section of sections$ | async;">
<div *ngFor="let card of section.card | sort:'displayOrder';">
<app-card></app-card>
<div *ngIf="card.cardTypeName === 'Table'">
<app-table></app-table>
</div>
</div>
</div>
Now the issue is when i try to load data for the table using updateTable [when user changes tablePerodID], it does nothing. I have tried .next()
but it updates whole section$
. Is there anyway i can only update table?
Thanks @adrisons for giving me the idea of caching. Here is the solution that worked for me. It is slightly different from @adrisons answer in a way that it doesn't use observable.
_cached: any;
sections$: Observable<any>;
loadPageData(Id): void {
// Load data from server
this.sections$ = this.psService.getLoadPageData(Id).pipe(
switchMap(sections => forkJoin(
sections.map(section => this.psService.getSectionData(section.sectionID).pipe(
map(card => Object.assign({}, section, { card })),
switchMap(c => c.card.map(card => iif(() => card.cardTypeId === 3,
from(this.psService.getTable(this.tablePerodID)
.pipe(map(table => Object.assign({}, c, { table })))),
of(c))))
).concatAll()
))
), first(), // Tap and get the first emit and assign to cache
tap((data: any) => {
this._cached = data // Caching the data without subscribing.
}));
}
updateTable(sectionId, tablePerodID) {
// Get table Data from backend and update cache
this.psService.getTable(tablePerodID).subscribe((data) => {
this._cached.map(section => {
if (section.sectionID === sectionId) {
section.table = data;
}
});
});
// Refresh async observable from cache
this.refreshFromCache();
}
refreshFromCache() {
this.sections$ = of(this._cached)
}