I am battling with combineLatest and scan rxjs operators (with Angular 8). Basically, I am displaying a list that can be filtered.
So I have a first Observable list$ = this.api.getAll()
and a second one filteredList$ = combineLatest(this.list$, this.form.valueChanges())
and, in my HTML, I'm displaying filteredList$
content using filteredList$ | async
.
This works fine (meaning, any change in the form update my filteredList$
)
However, the end user is able to update one element of the list ; when he does, I update my list$
Observable this way :
this.api.update(listElement)
.subscribe((updatedElmt) => {
this.list$ = this.list$.pipe(
concatMap(value => of(...value)),
scan((acc, listElmt) => listElmt._id === updatedElmt._id ? [...acc, updatedElmt] : [...acc, listElmt], []),
);
});
This also works well.
However, the combineLatest
is not triggered and therefore, my UI is never updated until I refresh my page. I assume it is because the list$
pointer has not change, so theere's no reason for the combineLatest to be triggered ; but how can I force it ?
BTW, using changeDetector to detectChanges or markForCheck does not work.
What exactly is it you want to achieve? If it is changing the updated Element in your list then you should consider something like this:
Define your List as Subject:
this.list$ = new Subject<ListType[]>();
Get the current list and next the list$
this.api.getAll().subscribe(this.list$.next); // dont forget to unsubscribe or youll get a memory leak
Observe for updates:
updateList$ = this.api.update(listElement).pipe(
withLatestFrom(this.currentList$),
map(([updatedElement, currentList]) => {
return currentList.map(listElement => listElement._id === udaptedElement._id ? updatedElement : listElement),
})
).subscribe(this.list$.next) // dont forget to unsubscribe (takeUntil()) should work here
Combine your list$ with valueChanges
combineLatest([this.list$, this.form.valueChanges()])).pipe(....)
this.list$ = ... sets a new value to the property, but combineLatest ist subscribing to the old value of this.list$. Which will result in a memory leak.
this.list$ = someObservableFunc$(); // gives first Observable<any>
const observeList$ = combineLatest([this.list$, otherObservable$]); // gives combination of first Observable<any> and otherObservable$
this.list$ = anotherObservableFunc$(); // gives second Observable<any> but observeList$ keeps subscription to first Observable<any>