I have a component in which I am displaying a table of data (users) generated from an http request to an API. There are a variety of filters on the table so I generate the table data as follows:
this.displayUsers$ = Observable.combineLatest(
this.users$,
this.siteFilter$,
this.clientFilter$,
this.activeFilter$,
this.nameFilter$
)
.map(([users, siteFilter, clientFilter, activeFilter, nameFilter]) => {
console.log("Users changed? ", users);
if (siteFilter === null
&& clientFilter === null
&& activeFilter === null
&& nameFilter.length < 1) {
return users;
}
return users
.filter(user => {
// manipulate users array based on filters
})
});
The xFilter$
s are BehaviorSubjects that emit new values in response to changes to their inputs in the template. users$
is assigned as follows:
this.users$ = this.userService.getList();
Where getList()
returns an http request to get a list of users.
The list successfully updates whenever the filters are changed, but I have issues when I need to update the list with fresh users. For example, a user can perform CRUD operations on the table of users (ie delete a user). When the user is deleted, however, the table does not update to reflect this change. The method I am currently using to (try) to fresh the table is by calling a refresh function in the success callback of the delete operation:
refreshUserList() {
console.log("Refreshing user list");
this.users$ = this.userService.getList();
}
Despite calling this after the operation is complete, the combineLatest observable does not get 'triggered' again and the list data remains stale. Is there a better way to refresh data generated by combineLatest with http requests?
The main problem is that in the case of user list update your users$ observable does not emit any new value. You have to make it do so.
This is skeleton of an idea how to fix it:
const updateUsersTrigger = new Subject<void>();
this.displayUsers$ = Observable.combineLatest(
// switchMap() will re-subscribe to this.userService.getList() observable on each emit from updateUsersTrigger
// thus making http requests each time when user list should be updated.
updateUsersTrigger.startWith(null).switchMap(() => this.userService.getList()),
this.siteFilter$,
this.clientFilter$,
this.activeFilter$,
this.nameFilter$
)
.map(([users, siteFilter, clientFilter, activeFilter, nameFilter]) => {
.......
});
// this will trigger user list update
updateUsersTrigger.next();