Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to compose observables using a ViewChildren event and void methods in angular 12?

I’m trying to create a typeahead that will call a service on keyup as the user types into an input box. My input is inside an *ngIf, so I’m using ViewChildren and subscribing to it’s changes to get the input. The method I am calling does not return a value, so I’m unsure how to properly compose rxjs operators to do this.

This is my current solution:

private searchBoxPlaceholder: ElementRef;
@ViewChildren("searchbox", { read: ElementRef }) elementRefs: QueryList<ElementRef>;

public ngAfterViewInit(): any {
  this.elementRefs.changes.subscribe(() => {
      if (this.elementRefs.toArray().length) {
        fromEvent(this.elementRefs.first.nativeElement, "keyup")
          .pipe(
            filter(Boolean),
            debounceTime(2000),
            distinctUntilChanged(),
            tap(() => {
              this.filterSearch(this.elementRefs.first.nativeElement.value);
            })
          )
          .subscribe();
      }
    });
  }

It works, but I feel like there is a better way to structure this without nesting subscribes. I’m also unsure if tap() is the best rxjs operator to use in this case. I’ve tried various combinations of switchMap, mergMap, concatMap, but since filterSearch does not return an Observable it’s not working for me.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Something like this… untested 🙂
FromEvent returns an Observable so you can use this within a switchMap and avoid the multiple subscribes. Also added takeUntil and a filter for the array length

 public ngAfterViewInit(): any {
    this.elementRefs.changes.pipe(
      filter(() => this.elementRefs.toArray().length > 0),
      switchMap(() => {
        return fromEvent(this.elementRefs.first.nativeElement, 'keyup')
          .pipe(
            filter(Boolean),
            debounceTime(2000),
            distinctUntilChanged(),
            tap(() => {
              this.filterSearch(this.elementRefs.first.nativeElement.value);
            })
          );
      }),
      takeUntil(this.onDestroy$)
    ).subscribe();

  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading