I've been working on a personal app. My goal is to have a search and delete users using Observables. For search functionality I have used this idea, this is how I implemented:
export class UserComponent implements OnInit {
users: Observable<User[]>;
private searchTerms = new Subject<string>();
ngOnInit(): void {
this.setUsers();
}
private setUsers(): void {
this.users = this.searchTerms
.debounceTime(300) // wait 300ms after each keystroke before considering the term
.distinctUntilChanged() // ignore if next search term is same as previous
.switchMap(term => term // switch to new observable each time the term changes
// return the http search observable
? this.userService.search(term)
// or the observable of all users if there was no search term
: this.userService.search(''))
.catch(() => {
this.response = -1;
return Observable.of<User[]>([]);
});
}
}
For delete functionality I use this:
private deleteSubject = new Subject();
delete(user: User): void {
this.userService
.delete(user)
.then(() => {
this.deleteSubject.next('');
})
.catch(() => {
console.log('error');
});
}
private setUsers(): void {
... // here comes the search functionality shown above
this.subscription = this.deleteSubject.subscribe(
(term: string) => this.users = this.userService.search(''),
(err) => console.log(err)
);
}
The problem that I faced with this implementation is that after I delete an user my search functionality is broken because I lost the subscriber for searchTerms
because I reassigned this.users
. So I've been searching and found that I can use merge
operator to append another subject, follow this idea. Sadly I'm facing a problem with the implementation. I tried this:
delete(user: User): void {
...
// change
this.deleteSubject.next('');
// with
this.deleteSubject.next({op: 'delete', id: user.id});
}
private setUsers(): void {
...
this.users.merge(this.deleteSubject)
.startWith([])
.scan((acc: any, val: any) => {
if (val.op && val.op === 'delete') {
let index = acc.findIndex((elt: any) => elt.id === val.id);
acc.splice(index, 1);
return acc;
} else {
return acc.concat(val);
}
});
But my scan
operator is never execute because this.deleteSubject
doesn't have a subscriber for it. I know how to create and associate a subscriber to my this.deleteSubject
but don't know how to mix it with my merge
operator. Also see that it's getting a bit complex, I guess it should be another way to get this done. Comments are appreciated.
Please take a look at my plunker, hope gets a bit clear. I've simulated the calls to my services using a memory array userList
.