Waiting for Subscribe in other method in Angular RxJS

@Component({
  selector: 'note-consultant',
  template: '<div>
    <div>{{patientInformation}}</div>
    <textarea #textElemRef></textarea>
    <button (click)="onSave()">Done</button>
    </div>'
})
export class NoteConsultantComponent implements OnInit, AfterViewInit { 
    recentResponse:any;
    patientInformation:any;
    @ViewChild('textElemRef') textElemRef: ElementRef;

    ngAfterViewInit(): void {
    fromEvent(this.textElemRef.nativeElement, 'keyup').pipe(
      map((event: any) => {
        return event.target.value;
      })
      ,debounceTime(1000)
    ).subscribe((text: string) => {

      let request = this.buildRequestItem(text);
        this.patientService.saveProblemNotes(request).subscribe((resp: any) => {
            if (resp.error) {
              console.log(resp.error);
              return;
            }

            //update response in temp variable...
            this.recentResponse = resp.problemText;
            }
        });
    }
    onSave() {
       if (this.recentResponse != null) {    
       //when clicking save button update DOM
       this.patientInformation = this.recentResponse;
     }

      //Reset temp variable
      this.recentResponse = null;
    }
}

I encountered a scenario where I needed to make an API call and save data whenever the user types text. To avoid hitting the API for every keystroke, I implemented the 'fromEvent' RxJs operator with debounce for a second.

In my case, I couldn't directly update the HTML while typing because it would cause certain elements to disappear, so I stored the response in a temporary variable called 'recentResponse'. When the Save button is clicked, I update the HTML based on this variable.

However, I faced an issue when users type fast and click Save immediately. It takes a few seconds until the Subscribe operation is finished, during which 'recentResponse' remains undefined, preventing 'patientInformation' and the corresponding HTML from updating.

Is there a way to ensure that the onSave function waits until the Subscribe operation is completed and 'recentResponse' has a valid response before proceeding?

Answer №1

To ensure the execution is deferred until typing has ceased, you can attach an event listener to the keyboard's keyup event using JavaScript and incorporate a timeout function.

HTML

<input type="text" (keyup)="onKeyUp($event)" />

TypeScript

timeout: number;

onKeyUp(event): void {
  if (this.timeout) {
    window.clearTimeout(this.timeout);
  }

  this.timeout = window.setTimeout(() => {
    // TODO: handle key up functionality here
  }, 500);
}

Answer №2

It is advisable to avoid calling the API on events like keyup, keydown, keypress, etc., as it will make a server request with every key press. Instead, consider using the blur event.

In response to your query:

Approach 1 - Disable Button Click: Simply disable the button until the API operation is complete.

fromEvent().subscribe(() => {
 disableBtn = true;
 this.patientService.saveProblemNotes(request).subscribe(() => {
  disableBtn = false; 
 })
})

Approach 2 - Observable: Encapsulate your API call within an observable and listen for its completion in the onSave function.

myApi() {
 new Observable(observer => {
  this.patientService.saveProblemNotes(request).subscribe(() => {
   observer.next();
  });
 });
}

onSave() {
 this.myApi.subscribe(() => {
  //API operation completed
 })
}

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

Evolving fashion trends

I'm looking to dynamically change the style of my HTML element based on screen size, similar to this example: <p [ngStyle]="{'color': isMobile() ? 'red' : 'blue'}">Lorem Ipsum</p> The code above triggers a m ...

Unable to input text in an Angular2 input field

Encountering an issue with users on Windows 7 using IE11 while trying to input information into textboxes or textareas. The drop-downs and checkboxes are functioning properly, but additional fields cannot be filled out even after toggling visibility with t ...

Tips for integrating TypeScript with Vue.js and Single File Components

After extensive searching online, I have struggled to find a straightforward and up-to-date example of setting up Vue.js with TypeScript. The typical tutorials out there either are outdated or rely on specific configurations that don't apply universal ...

Angular 2 Login Component Featuring Customizable Templates

Currently, I have set up an AppModule with a variety of components, including the AppComponent which serves as the template component with the router-outlet directive. I am looking to create an AuthModule that includes its own template AuthComponent situa ...

Creating an Http interceptor in Ionic 3 and Angular 4 to display a loading indicator for every API request

One of my current challenges involves creating a custom HTTP interceptor to manage loading and other additional functions efficiently. Manually handling loading for each request has led to a considerable increase in code. The issue at hand: The loader is ...

Encountering difficulties while attempting to transition from angular 9 to angular 10

I attempted to upgrade my Angular project by running the following commands: $ ng update @angular/core@9 @angular/cli@9 $ ng update @angular/core @angular/cli However, when I executed the last command in the console, it resulted in an error message: Your ...

Link the chosen selection from a dropdown menu to a TypeScript object in Angular 2

I have a form that allows users to create Todo's. An ITodo object includes the following properties: export interface ITodo { id: number; title: string; priority: ITodoPriority; } export interface ITodoPriority { id: number; name ...

Can you please provide me with the compilerOptions properties needed to create a .js file from a .tsx file in React Native using TypeScript?

For the past day, I've been diving into typescript in react native. Setting up typescript in my react-native project has been a focus as I try to convert .tsx files into .js files within the realm of react native typescript. I attempted to tweak the ...

Retrieve the mfData value from the TypeScript file in order to perform operations on it within the Angular 2 framework

I have a snippet of code that iterates through data from stacklist_table, which is a JSON array, and displays it in a table format. The stacklist_table contains a full list of objects, but I only need a subset of these objects so I have applied some filter ...

Issues encountered when retrieving data with ReactiveForms

My current project involves gathering data using ReactiveForms. Here is the structure of my setup: Initially, I create a modal to gather the necessary data: async present(){ const modal = await this.modalController.create({ component: dataComponent, cs ...

Multiple Invocations of Angular NgrxStore Action Dispatched within Selector Function

Currently, I am working on an Angular project utilizing ngRx store for the first time. In this project, I need to dispatch an action to fetch users' courses after retrieving the user from the Store. However, I have encountered a problem where the acti ...

The build process is encountering issues with lodash causing npm to fail

Utilizing Node: 16.20.2 Angular: CLI 11.2.5 Typescript: 4.1.5 @types/lodash: 4.14.177 An issue has arisen where the npm build process is failing with the following exception: Error: node modules/@types/lodash/common/object.d.ts:1026:46 error TS1 ...

Whenever a file is chosen, I aim to generate the video HTML dynamically and display the video with play functionalities using Angular 2 and TypeScript

I am attempting to allow users to select a video file and display it so they can play it after choosing the file. Below is my HTML code: <br> <input type="file" (change)="fileChangeEvent($event)" placeholder="upload file..." class=" ...

Is there a way to assign API data as inner HTML using Lit?

Need help setting inner html of html elements with a get request Any suggestions on how to achieve this? import { LitElement, html, css } from "lit"; import { customElement } from "lit/decorators.js"; import axios from "axios" ...

When there are multiple tabs open in the browser, I notice a difference in the time displayed. This occurs in an Angular 2 environment

https://i.sstatic.net/l4YQ1.pngAfter a successful login, I am fetching server time from the back-end (in Java) and adding 1 second at intervals. Observable.interval(1000).map(() => { return this.time.add(1, 'seconds'); }). ...

Angular EventEmitter coupled with Callbacks

In order to create a custom button component for my angular application and implement a method for click functionality, I have the following code snippet: export class MyButtonComponent { @Input() active: boolean = false; @Output() btnClick: EventEmit ...

In JavaScript, sort the array of objects based on the key name

I have an array of objects like the following: employees = [ {name: "Tony Stark", department: "IT"}, {name: "Peter Parker", department: "Pizza Delivery"}, {name: "Bruce Wayne", department: "IT"}, {name: "Clark Kent", department: "Editin ...

Encountering an issue with the date pipe in Angular that prevents

I'm trying to incorporate a date pipe in my AngularJS and Firebase project to display the creation date of a post. However, I am facing an issue where the date does not appear when testing it. Below is my create Post function: createPost() { con ...

One function in Typescript lodash is missing a default export

Is there a way to import just one function from lodash? I attempted it like this: import get from 'lodash/get'; Even after installing both lodash and @types/lodash, I encountered the following error message: @types/lodash/get/index"' ha ...

Is it possible to switch the hamburger menu button to an X icon upon clicking in Vue 3 with the help of PrimeVue?

When the Menubar component is used, the hamburger menu automatically appears when resizing the browser window. However, I want to change the icon from pi-bars to pi-times when that button is clicked. Is there a way to achieve this? I am uncertain of how t ...