1

I'm struggling to figure the correct way to filter an array of objects using RxJS 6.

Here's the scenario. I have users: User[], filter: FormControl, and another array of filteredUsers: User[]. What I would like to do is filter the list the users based on the value contained in the filter. The only way I was able to figure this out was to use tap, and while this works, it just doesn't seem like the right way to do it...plus the whole list is "filtered out" until the filter control has its first valueChange.

this.filter.valueChanges.pipe(
  tap((term) => {
    this.filteredUsers = this.users.filter(u => u.name.indexOf(term) != -1)
  })).subscribe()

Any help would be greatly appreciated.

2 Answers 2

2

you're right that tap isn't the "right" way to do it... the right way is to do it in subscribe...

this.filter.valueChanges.pipe(startWith('')).subscribe(
  (term) => {
    this.filteredUsers = (term) ? this.users.filter(u => u.name.indexOf(term) != -1) : this.users;
});

and add in a blank check that doesn't filter, and a start with that kicks off the stream. done and done. Don't add complexity where you don't need it. rxjs recommends side effects occur in your subscribe function, everything else SHOULD be transformative / functional, and setting a value on the controller is a side effect.

If you want to get really reactive, you can throw in an async pipe for good measure

this.filteredUsers$ = this.filter.valueChanges.pipe(startWith('')).tap(
  (term) => {
    return (term) ? this.users.filter(u => u.name.indexOf(term) != -1) : this.users;
});

then in HTML instead of

*ngFor="let user of filteredUsers"

do:

*ngFor="let user of filteredUsers$ | async"

the benefit here is automatic subscription cleanup and better support for onpush change detection.

Sign up to request clarification or add additional context in comments.

Comments

0

Just move the tap function into the subscribe:

this.filter.valueChanges.subscribe((term) => {
    this.filteredUsers = this.users.filter(u => u.name.indexOf(term) != -1)
  });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.