Creating custom observables by utilizing ViewChildren event and void functions in Angular 12: A step-by-step guide

I am currently working on developing a typeahead feature that triggers a service call on keyup event as the user types in an input field. The challenge I face is that my input field is enclosed within an *ngIf block, which requires me to utilize ViewChildren and subscribe to its changes to access the input element. However, the method being called does not return any value, making it difficult for me to correctly structure rxjs operators for this task.

Below is my existing implementation:

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();
      }
    });
  }

Although this solution works, I believe there might be a more efficient way to organize this code without nesting multiple subscribes. Additionally, I am uncertain whether tap() is the most suitable rxjs operator for this scenario. I have experimented with switchMap, mergeMap, and concatMap variations, but due to filterSearch not returning an Observable, I have not been successful in achieving the desired outcome.

Answer №1

Here is a potential solution, though it has not been tested yet: Using the FromEvent method will return an Observable, allowing you to utilize it within a switchMap function to avoid multiple subscriptions. Additionally, I have included takeUntil and implemented a filter based on 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();

  }

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilize a dynamically defined union type to create a versatile callback function

I'm currently working on creating a message subscription function. A basic version without types is shown below: function createMessage(message) { postMessage(message) } function addSubscriber(messageType, callback) { handleNewMessage(message =&g ...

Which specific version of @angular/material should I be using?

After starting a new project, I encountered an issue while trying to install ng add @angular/material. The error message received was: # npm resolution error report While resolving: @angular/<a href="/cdn-cgi/l/email-protection" class="__cf_email__ ...

Modify/remove table using a popup window

My goal was to include edit and delete buttons within a table. When these buttons are clicked, a popup window opens allowing us to modify the values and then update them in the table using Angular. ...

Stop SVG Image Caching in Angular

I encountered an issue while attempting to dynamically load an image in Angular without caching. The error I saw in the console was: ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous v ...

The variance between executing code with and without breakpoints in JUnit using Selenium's Chrome Driver

My goal is to complete the sign-in page and then use selenium to navigate to a custom form. Everything seems to be working fine when I have a break point set, but as soon as I remove it, the session gets cleared out. The Angular authentication mechanism re ...

What is the syntax for declaring a boolean or object type?

Is it possible to create a variable in TypeScript that can hold either true/false or an object of booleans? I'm still learning TS and would like some input on this syntax. variableA: { a: boolean, b: boolean } | boolean I found a workaround for now, ...

Error: No default Firebase App named '[DEFAULT]' exists. Please remember to call Firebase App.initializeApp() to create the app (app/no-app). This issue is located at the app

Currently, I am in the process of learning how to integrate Firebase Functions into an Ionic + Angular project. My goal is to develop a custom function that retrieves all games from a collection and returns an array sorted by the "count" attribute. Initia ...

The distribution of intersection types is not properly handled by Typescript's array.map function

My array is of type object[] & Tree[], but when using arr.map(child => ...), the type of child is inferred as object instead of object & Tree. Is there a way to avoid this without additional casting? It's worth noting that Tree extends ob ...

Transitioning an NX environment to integrate ESM

My NX-based monorepo is quite extensive, consisting of half a dozen apps, frontend, backend, and dozens of libs. Currently, everything is set up to use commonjs module types, as that's what the NX generators have always produced. However, many librar ...

reactjs: disable a specific eslint rule

I'm trying to figure out how to disable the "no-unused-vars" rule specifically for TypeScript interfaces. Here's a code snippet where I'm getting a warning: export type IKeoTableColumn<T> = { id: T; align: 'left' | ' ...

Error Encountered: Anticipated 'styles' to consist of a series of string elements

I have attempted various solutions for this particular error message without any success. When launching my angular project using the angular cli via ng serve, everything runs smoothly with no errors. However, upon compiling it with webpack, I encounter th ...

Enhancing code completion with IntelliSense for customized styled components' themes

When using a theme in styled components, I am attempting to enable IntelliSense. In my code snippet below (index.tsx), I utilize ThemeProvider: import React from 'react'; import ReactDOM from 'react-dom/client'; import { ThemeProvider } ...

Utilizing Dynamic Class Names in Angular 7 with Typescript

In the process of developing an Angular 7 application, I have created a form component that is intended to be used for various entities. As part of this, I defined a variable route: {path: ':entity/create', component: FormComponent} While this ...

Unable to find the module... designated for one of my packages

Within my codebase, I am utilizing a specific NPM package called my-dependency-package, which contains the module lib/utils/list-utils. Moreover, I have another package named my-package that relies on my-dependency-package. When attempting to build the pr ...

Error: Angular - encountering undefined response when making HTTP request

When making a HTTP GET request to my backend, it returns the following JSON data: "{\"instID\":\"2018#10#30\",\"procID\":1161006,\"threadNum\":0,\"status\":2}", "{\"instID\":\"2018#1 ...

Issue with data-* attributes in MaterialUI React component causing TypeScript error

I am encountering an issue while attempting to assign a data-testid attribute to a Material-UI Select component. The Typescript error I am facing is as follows: Type '{ "data-testid": string; }' is not compatible with type 'HTMLAttributes&a ...

What is the best approach for injecting services (local and API) in Angular 13 based on different environments (local and QA)?

api-local.service.ts import { Injectable } from '@angular/core'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { LoginRequest } from '../login/login-request'; @Injectable({ providedIn: 'root&ap ...

Dynamically attach rows to a table in Angular by triggering a TypeScript method with a button click

I need help creating a button that will add rows to a table dynamically when pressed. However, I am encountering an error when trying to call the function in TypeScript (save_row()). How can I successfully call the function in TypeScript and dynamically a ...

TypeORM find query is returning a data type that does not match the defined entity type

In my infrastructure module, I am using the code snippet below: import { Student } from "core" import { Repository } from "./Repository" import { Database } from "../../db" export class UserRepository<Student> extends Re ...

Greetings, Angular2 application with TypeScript that showcases the beauty of the world

I've been working on my first angular2 program and noticed some deviations from the expected output. typings.json: { "ambientDependencies": { "es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#7de6c3dd94feaeb21f20054b9f ...