Combine all the missing observables in RxJS into a single array

In my code, I am creating a NavBar with items that may require fetching extra information from an API and adding it to the subtitle field.

I want to transform this into an Observable<NavItem[]> so that it can be rendered using an Async Pipe.

Currently, the code logs each NavItem before calling ops.toArray(). However, the log call after ops.toArray() never completes...

Is there a more efficient RXJS approach to combine these items into an Observable<NavItem[]> ?

import * as ops from 'rxjs/operators';

navItem$: Observable<NavItem[]> = null

this.navItem$ = this.store.pipe(
  select(fromRoute.selectLastUrls),
  ops.map((d) => {
    // Initial creation of NavItems
  }),
  ops.tap((i) => console.log(i)), // Prints an array of 5 NavItems as expected
  ops.mergeAll(),
  ops.mergeMap((i) =>
    iif(
      () => i.listItem,
      // Make API calls for certain list items (To include subtitle details)
      this.backendService.find({ title: [i.title] }).pipe(
        ops.map((found) => ({...i, subtitle: found.items[0].info,})),
      ),
      of(i),
    ),
  ),
  ops.tap((i) => console.log(i)), // Each log line should contain 1 NavItem with data retrieved from API calls
  ops.toArray(),
  ops.tap((i) => console.log(i)) // This line fails to log
);

Answer №1

in this particular scenario, the function toArray is programmed to wait for the entire stream to finish before compiling all elements into a single array.

If you want this operation to only apply to grouped items, you will need to nest the operators one level deeper. Below is an example of how to achieve this:

this.navItem$ = this.store.pipe(
  select(fromRoute.selectLastUrls),
  ops.map((d) => {
    // Initial setup of NavItems
  }),
  ops.tap((i) => console.log(i)), // Outputs an array of 5 NavItems as anticipated
  ops.switchMap(arr => from(arr).pipe(
     ops.mergeMap((i) =>
       iif(
        () => i.listItem,
         // Fetch additional details from API for list items (e.g., subtitle)
         this.backendService.find({ title: [i.title] }).pipe(
           ops.map((found) => ({...i, subtitle: found.items[0].info,})),),
         of(i),
       ),
     ),
     ops.tap((i) => console.log(i)), // Each log line should display 1 NavItem with data retrieved from API calls
     ops.toArray(),
    ))
  
  ops.tap((i) => console.log(i)) // Logs arrays after the modification
);

It's worth noting that importing all operators using

import * as ops from 'rxjs/operators';
is not recommended because it may result in unnecessary operators being included in the bundle. Importing each operator individually allows for better tree-shaking and a smaller final bundle size.

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

Tips for Angular 14: How to clearly define a form control as not being undefined

Consider a scenario with a form setup like this: searchForm = new FormGroup({ SearchBox = new FormControl<string>('', {nonNullable: true}); )} Now, when attempting to extract the value from the form field using this code snippet: thi ...

How is it that the chosen attribute functions for every ng-container?

I have 2 ng-containers. When I am in one view, I want "My Appointments" selected in the options dropdown when navigating to that view. In the other view, I want "Active" selected in the options dropdown. Here is my html code: <div class="wrapper w ...

Error message: Angular 2's NgFor directive can only bind to iterable data types like Arrays

One of the challenges I'm facing involves working with a specific model: export class CoreGoalModel { constructor( public title: string, public image: string, ){} } In order to retrieve data based on this model, I've set up a s ...

Using React Material UI in Typescript to enhance the theme with custom properties

Struggling to customize the default interface of material ui Theme by adding a custom background property to palette. Fortunately, I found the solution thanks to this helpful shared by deewens. declare module '@material-ui/core/styles/createPalette& ...

Eliminate the chosen and marked items from a list - Angular 2+/ Ionic 2

Currently, I have a checkbox list on my page. Whenever a user selects the "Save" button, the checked items should be removed from the list and moved to the saved tab that is also displayed. While I have successfully implemented the functionality for removi ...

Are Angular 4 auth guards implemented on the server side or the client side? And if they are on the client side, are they vulnerable to

While I am engaged in a project using Angular 4, my expertise lies in angular auth-guards. Here's my query: considering that Angular 4 is primarily a client-sided framework, is it possible to bypass the auth-guard by inspecting the browser window, giv ...

Exploring ngTemplateOutlet and ngtemplate in complex nested forms with Angular

I am currently working on generating reactive forms from JSON data. My goal is to create a formGroup and its nested forms based on the provided data, and automatically generate an HTML form using templates. I have outlined the steps I took with sample data ...

What strategies can be utilized to manage a sizable data set?

I'm currently tasked with downloading a large dataset from my company's database and analyzing it in Excel. To streamline this process, I am looking to automate it using ExcelOnline. I found a helpful guide at this link provided by Microsoft Powe ...

Have I repeated myself in defining my class properties?

Currently, I'm enhancing my understanding of Typescript with the development of a discord.js bot. However, I have come across a piece of code and I am uncertain about its redundancy: import Discord from 'discord.js'; export default class B ...

What is the best way to apply CSS to a mat-row element only when it is being hovered over?

I have a table with rows where a specific condition triggers a light red background color for each row. On hover, the background changes to light gray for all rows. However, I need the special rows (already colored light red) to have a deeper shade of red ...

Repetitive cycling through an array

My array consists of classes: const transferClasses = [ { id: "c5d91430-aaab-ed11-8daf-85953743f5cc", name: "Class1", isTransfer: false, children: [], }, { id: "775cb75d-aaab-ed11-8daf-85953743f5cc", ...

The supplied parameters do not correspond with any valid call target signature for the HTTP delete operation

I've been attempting to utilize the http delete method in Angular 2, but I keep encountering a typescript error: Supplied parameters do not match any signature of call target.. Below is the code I am using: let headers= new Headers(); ...

What is the solution for fixing an error that says "There is no 'style' property on the 'Element' type"?

I'm struggling to fix an error in my JavaScript code. I created a script to display a tab indicator when a tab is clicked, but I keep getting the error message: "Property 'style' doesn't exist on type 'Element'". The tabs them ...

Unsuccessful invocation of React's componentDidMount method

Our UI designer created a Tabs component in React that allows for selecting and rendering child components based on index. However, I am facing an issue where the componentDidMount function is not being called when switching between tabs. I have implement ...

Troubleshoot: Angular hide/show feature malfunctioning

I am facing an issue where clicking on one parent element causes all parent elements to show or hide their child elements accordingly. I am relatively new to Angular 2 and would appreciate any recommendations. Below, you can see the code for the component ...

Error Alert: Redux unable to retrieve data from Django API due to CORS issue

Currently, I am working on a project with a frontend application running on http://localhost:3000 and a backend API on http://localhost:8000. However, I am facing a CORS issue when trying to make requests from the frontend to the backend API. The error me ...

TypeScript properties for styled input component

As I venture into TS, I’ve been tasked with transitioning an existing JS code base to TS. One of the challenges I encountered involves a styled component in a file named style.js. import styled from "styled-components"; export const Container ...

Cross-origin resource sharing (CORS) seems to be creating a barrier for the communication between my Angular

During the process of developing an Angular and NestJS app with NGXS for state management, I encountered a CORS error while serving my application. The error message in the console indicated: Access to XMLHttpRequest at 'localhost:333/api/product-i ...

What purpose does a private property serve within the interface?

Given the following code snippet: class X { bar() { return "bar" } constructor(private readonly x: number){} } interface Y extends X { } const f = (y: Y) => { console.log(y.bar()); } f({ bar: () => "tavern"}); The code does ...

Error in Angular 2.0 final version: Unable to access the 'injector' property of null object

Upon transitioning from Angular 2 RC5 to 2.0 Final, I've encountered some errors while running my tests. It's puzzling me as to what could be causing this issue. TypeError: Cannot read property 'injector' of null at TestBed._create ...