How can I merge these two Observables in Angular to create an array of objects?

Let's say we are working with two different datasets:

 student$ = from([
    {id: 1, name: "Alex"},
    {id: 2, name: "Marry"},
  ])

  address$ = from([
    {id: 1, location: "Chicago", sid: 1},
    {id: 2, location: "Florida", sid: 2},
  ])

The task at hand is to merge these two datasets into an array of objects. The desired output should resemble the following structure:

  studentAddress = [
    {
      id: 1,
      name: "Alex",
      address: [
        {id: 1, location: "Chicago", sid: 1},
      ]
    },
    {
      id: 2,
      name: "Marry",
      address: [
        {id: 2, location: "Florida", sid: 2},
      ]
    },
  ]

Answer №1

If your students$ and address$ observable both emit arrays of objects.

  address$ = of([
    { id: 1, location: 'Chicago', sid: 1 },
    { id: 2, location: 'Florida', sid: 2 },
  ]);

  students$ = of([
    { id: 1, name: 'Alex' },
    { id: 2, name: 'Marry' },
  ]);

You can utilize the RxJs function combineLatest: This function combines multiple Observables to create an Observable whose values are calculated from the latest values of each input Observable.

combineLatest will wait to emit a value until all observables have emitted at least one value

combineLatest(
  [this.students$, this.address$],
  (students, address) =>
    students.map((s) => ({
      ...s,
      address: address.filter((a) => a.sid === s.id),
    })) // You can also use an optional projection function with combineLatest
).subscribe(console.log);

Required imports:

import { combineLatest, of } from 'rxjs';

Check out the Angular Demo showcasing the usage of combineLatest and forkJoin

Note: Instead of combibeLatest, you may consider using forkJoin in your scenario. forkJoin emits a value only when all observables have completed and then emits the last emitted value from each.

Answer №2

To accomplish this task, consider utilizing the flatMap method from RxJs. This method allows you to pass the first value needed by the second one. Below is a code snippet example demonstrating the use of flatMap(), and also a link to an article showcasing other methods (the example below is extracted from the same article).

let first = Observable.of(10);
first.flatMap((operand1) => {
  return Observable.of(operand1 + 10);
 })
.subscribe(res => this.flatMappedStreams = {msg: '10 + 10 = ' + res});

For additional methods like concat, combine, forkJoin, you can refer to this article here

The key factor lies in understanding RxJs Operators. For further insight, consult their official documentation

Answer №3

Based on your observation about the arrays being retrieved from nested HTTP calls, it appears that you would benefit from

  • switchMap operator to transition from one HTTP call to another (other higher order mapping operators)
  • map operator for modifying data emitted by the observable
  • Array#map in conjunction with Array#filter for combining the arrays

var { of } = rxjs;
var { switchMap, map } = rxjs.operators;

const students$ = of([
  {id: 1, name: "Alex"},
  {id: 2, name: "Marry"},
]);

const addresses$ = of([
  {id: 1, location: "Chicago", sid: 1},
  {id: 2, location: "Florida", sid: 2},
]);

const result$ = students$.pipe(
  switchMap(students =>
    addresses$.pipe(
      map(addresses => 
        students.map(student => ({
          ...student,
          address: addresses.filter(address => address.id === student.id)
        }))
      )
    )
  )
);

result$.subscribe(console.log);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e193998b92a1d7cfd5cfd1">[email protected]</a>/bundles/rxjs.umd.min.js"></script>

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

Errors encountered: Navigation guard causing infinite redirection due to unhandled runtime issue

My Vue3 router is set up with the following routes: export const routes: Array<RouteRecordRaw> = [ { path: "/", name: "Browse Questions", component: HomeView, meta: { access: "canAdmin", }, ...

Using Vue.js to group JSON arrays multiple times

I have a program that I utilize to import a CSV data file and then convert it into JSON format. The resulting JSON structure is as follows: { "Class": "Cultivated Mushrooms", "Type": "Shii-take", "Grade": "Medium", "LvH": "SP", "Description": " ...

Generating Typescript definition files from JavaScript files with module.exports assignment

I'm currently working on creating a custom TypeScript definition file for format-duration: module.exports = (ms) => { let { days, hours, minutes, seconds } = parseMs(ms) seconds = addZero(seconds) if (days) return `${days}:${addZero(hours)}: ...

Consolidate all scripts into a single file with Asp.net MVC 5 bundling

On one of my razor pages, I have the following script section: @Scripts.Render("~/bundles/script1") @Scripts.Render("~/bundles/script2") @Scripts.Render("~/bundles/script3") The issue is that it renders three separate JavaScript files. Is there a way to ...

JavaScript: Obtaining the month based on the week number and year

Can someone assist me in determining the month based on a given week number and year? For example: Week - 48 Year - 2023 Desired Output - 11 ...

Execute Javascript after modification of the DOM

I have developed two custom directives known as app-content and app-content-item. These directives are intended to be utilized in upcoming projects to provide a basic structure with simple styling. They will be incorporated into a module and should be nest ...

Using React to easily rearrange images by dragging and dropping them

Currently, I am working on incorporating drag-and-drop functionality using React JS along with the react-dropzone library to display thumbnails. The code implementation is provided below: import React from "react"; import ReactDOM from "react-dom"; impor ...

Issues with React and Recharts legend functionality causing disruptions

I am currently experimenting with React and Recharts to build a stacked and grouped bar chart. This is my first experience using Recharts, and I have encountered an issue with the legend functionality. I would like the legend to toggle both graphs within e ...

Looking to add a dropdown feature to my current main navigation bar

I've been struggling to add a drop-down menu to my website's main menu. Every time I try, something goes wrong - sometimes the menu appears inline, other times it completely messes up the layout. Here is the HTML code snippet: <ul class="m ...

Navigating with Angular's router occurs before the guard is fully completed

Within my Angular 8 application, the routing file is structured as below: const myRoutes: Routes = [ {path: '', component: FirstComponent , canActivate: [RegistrationSrcdGuard]}, {path: 'FirstComponent ', component: FirstCompon ...

Retrieve, establish cookies, and guard against CSRF attacks

Having some difficulty with CSRF in my application while using Isomorphic fetch. The backend sends a CSRF-TOKEN in the set-cookies property: There is advice against directly accessing these cookies in code, so I attempted utilizing the credentials proper ...

The name 'withStyles' is nowhere to be found

import * as React from "react"; import Button from "@material-ui/core/Button"; import * as PropTypes from "prop-types"; import {WithStyles} from '@material-ui/core'; import "./App.css"; import PageTwo from "./components/PageTwo"; ...

Combining ng-repeat with manipulating the DOM beyond the scope of a directive

I'm struggling to understand Angular Directives and how they work. I have a simple array of objects in my controller, but creating the desired DOM structure from this data model is proving challenging. Any advice on best practices would be greatly app ...

Tips for maintaining the reference of a Three.js object after importing it as an .obj file

If you want to learn how to incorporate a .obj file into your scene, the official documentation provides a helpful example that can be found here. const loader = new OBJLoader(); // Load the resource loader.load( // Resource URL 'models/monst ...

Initializing a table with data will only function properly when a breakpoint is set

Using the bootstrap-table library, I initialize a table with data fetched via ajax request. var arr = []; var getRows = function () { $.ajax({ type: "GET", url: hostUrl, contentType: "app ...

Updating parent array values within child components in React

Currently, I am working on a React application where I need to save the handlers for all windows opened from the app. Previously, before using React, I stored these windows in a global array attached to the parent window, although I understand that using J ...

Receiving unexpected results when returning a function within a React hook

I'm currently working on developing a custom React hook that will provide users with a function to execute. This hook is designed to generate a function internally. Check out this simplified example // fetch.js import { useEffect, useState} from &qu ...

Deliver a JSON response using Express

Attempting to implement a chat-gpt response in Node, I encountered an issue where the server is not serving up the data successfully, only returning {}. index.js import gptSummary from "./gptFunc.js"; import express from "express"; co ...

How can we limit the generic type T in TypeScript to ensure it is not undefined?

I have created a function called get(o, key), which is designed to work with any Object that meets the criteria of the { get: (key: K) => R } interface. Furthermore, I am interested in restricting the result variable R to not allow it to be undefined. ...

The React application is showing an empty page without any visible errors during the compilation process

I'm having trouble with my React app - it compiles without errors but only shows a blank page. Can someone help me figure out what's wrong with my code? I'm new to React and could use some guidance. index.js import React from 'react&ap ...