Manage sequential observables and await user input

I have a collection of items that I need to loop through in order to determine whether or not a modal dialog should be displayed to the user, and then pause the iteration until the user provides input. The items are stored within an observable as

Observable<Array<Item>>;
.

Each item in the array needs to be checked to see if its type is already included in a Map<ItemType, string> object. If it is not present, a modal prompting the user to enter a comment should appear, and the entered value should be saved in the map. If the type is already present, no action should be taken and the iteration should continue. Below is some pseudo code illustrating what I am trying to accomplish.

Map<ItemType, string> comments;
Observable<Array<Items>> items;

foreach (item in items) {
    if(comments[item.type]) {
        continue to next item;
    } else {
        show a modal dialog and wait for the userInput;
        onModalClose -> comments[item.type] = userInput
    }
}

The modal itself returns a new observable containing the user's input.

My challenge lies in figuring out how to handle waiting for the modal observable to complete before proceeding with the iteration of the observable array, the RxJs way. Using promise chains would not be difficult for me.

I have attempted several approaches but I may have become too overwhelmed by my efforts to clearly understand the solution. My most recent attempt, although likely far from ideal, is shown below.

this.items$.pipe( //Observable<Array<Item>>
      map(items => items.map(i => of(i))), //Convert to an Array<Observable<Item>>
      switchMap(items => { 
        return concat(...items).pipe(
          switchMap(item => {
            return this.showExtraInformationModal().pipe(
              map(resultFromModal => {
                // Use the result from modal 
              })
            );
          })
        )
      })
    ).subscribe();

What is the correct way to address the "Wait for user input and then continue!" situation with observables?

Answer №1

Your approach is almost there, but could use a bit of simplification:

items$.pipe(
  mergeMap(items => items), //transforms Observable<Array<T>> into individual items stream
  concatMap(item => 
    item.showModal ?
      showExtraInformationModal().pipe(
        map(resultFromModal => {
          // Utilize the result from modal 
        }))
      :
      of(item)
  )
).subscribe();

By using concatMap, you can delay processing until the inner observable completes.

Make sure your "Show/Not Show Modal" logic is inside the concatMap function.

Check out this demonstration: https://stackblitz.com/edit/rxjs-sxeude?file=index.ts

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

Need to transfer data from an Angular 5 application to a server-side file using PHP, but

I am experimenting with sending an encrypted variable from Angular to a PHP script for testing purposes. Below is the client-side script: ngOnInit(){ let user = "am"; let key = "pizza"; let enc = crypto.AES.encrypt(user, key); console.log(enc); let dec = ...

Node.js/Express API Endpoint Ceases Functioning

In my Angular/Express.js app, there is a post method within my api.service.ts file: post(data: any, endpointUrl: string): Observable<T> { console.log("REACHED POST METHOD") return this.http.post<T>(`${this.apiUrl}/${endpoint ...

What is the best way to change a blob into a base64 format using Node.js with TypeScript?

When making an internal call to a MicroService in Node.js with TypeScript, I am receiving a blob image as the response. My goal is to convert this blob image into Base64 format so that I can use it to display it within an EJS image tag. I attempted to ach ...

Callbacks are never fired in SQL Server because of the tedious connection

I have successfully connected to a SQL Server instance hosted in Azure through DBeaver and can browse all the data. After installing tedious with the following commands: npm install tedious npm install @types/tedious This is the exact code I am using: im ...

It seems like there is an issue with your network connection. Please try again

Recently, I made the switch to EndeavourOS, which is based on Archlinux. I completed all my installations without any issues and attempted to create a new NestJs project after installing NVM, Node's latest version, and the NestJs/cli. However, when I ...

Getting a response directly from an HttpRequest and assigning it to a variable

Can someone help me with this issue: // api-service.ts fetchUsers() { return this.http.get(this.BaseUrl + 'users/', httpOptions); } I am trying to assign the result of this API call to a variable like so : // users-component.ts ngOnInit() ...

Create collaborative documents with serverless TypeScript extension

Utilizing Amazon Lambda AWS along with Serverless and the Serverless Plugin TypeScript to develop my TypeScript files has been quite a challenge. I have implemented shared code in my project, organized within folders such as: /shared: shared1.ts, shared2. ...

Tips for making the onChange event of the AntDesign Cascader component functional

Having an issue with utilizing the Cascader component from AntDesign and managing its values upon change. The error arises when attempting to assign an onChange function to the onChange property of the component. Referencing the code snippet extracted dire ...

What is the process for importing an mp3 file into a TypeScript project?

I'm currently working on a web application using React and TypeScript. My current challenge involves importing an mp3 file for use with the use-sound library, but I keep encountering this error in TypeScript: "Cannot find module '../../as ...

Assets failing to duplicate during ng build in production

Currently, I'm developing an application using Angular 4. I recently added a new SVG image to the assets/images folder and made the necessary changes in the angular-cli.json file as well. When I run 'ng build' locally, it successfully copies ...

Startling error: Our node server.js running into an unexpected token

I'm attempting to follow the Angular Universal quickstart, but I encountered an error when running "node server.js". Emily's-MBP:vepo Emily$ node server.js /Users/Emily/Development/vepo/server.js:3 import 'angular2-universal/polyfills&apos ...

The page refreshes when the anchor element is clicked

Currently, I am working on enhancing a web application that is built on the foundation of traditional aspx (asp.net) web forms with elements of Angular 6 incorporated into it. My current assignment involves resolving a bug that triggers a page refresh whe ...

Bringing together projects utilizing varying Typescript versions within Visual Studio 2015

When working with VS2015-SP2, imagine a solution that contains two typescript projects. One project is using version 1.5 and the other is using version 1.7. How will the compiler handle this situation? ...

The process of sorting through an array of objects based on their specific types in TypeScript

I am working on a function that filters an array of objects based on their type property: export const retrieveLayoutChangeActions = (data: GetOperations['included']) => data.filter(d => d.type === 'layoutChangeAction') as Layou ...

Event triggered by clicking on certain coordinates

Just starting with @asymmetrik/ngx-leaflet and Angular, so this might be a beginner's issue... I'm working on an Angular.io (v5) project that incorporates the @asymmetrik/ngx-leaflet-tutorial-ngcli Currently, I'm trying to retrieve the coo ...

I encountered TS2345 error: The argument type X cannot be assigned to the parameter type Y

Currently, I am delving into the world of Angular 8 as a beginner with this framework. In my attempt to design a new user interface with additional elements, I encountered an unexpected linting error after smoothly adding the first two fields. The error m ...

Limit Typescript decorator usage to functions that return either void or Promise<void>

I've been working on developing a decorator that is specifically designed for methods of type void or Promise<void>. class TestClass { // compiles successfully @Example() test() {} // should compile, but doesn't @Example() asyn ...

Issue with deep linking functionality on S3 storage service turning out to be

After successfully deploying my angular5 app to: http://myApp.s3domain.amazonaws.com The Angular router is automatically directing me to http://myApp.s3domain.amazonaws.com/home However, when I try to access a link with a unique parameter like so: http:/ ...

BS Modal was improperly invoked, leading to an illegal instantiation

Currently, I am attempting to trigger a bootstrap Modal in Angular by utilizing the component instead of its HTML attribute. However, I am encountering an error (specifically, illegal invocation). Here is the code snippet from the component: @ViewChild(&a ...

typescript create object with immutable property already set

Can you create an object literal in JavaScript and define its interface with read-only properties simultaneously? For instance let obj = { readonly prop1: 'hello', readonly prop2: 'world' } ...