Combining 2 lists in Angular Firebase: A Simple Guide

I have been searching for a solution for the past 2 hours, but unfortunately haven't found one yet. Although I have experience working with both SQL and NoSQL databases, this particular issue is new to me. My problem is quite straightforward: I have two collections - Raw Materials and Raw Materials Stock. Each document in the Raw Materials Stock collection includes a key for the raw material. What I need to do is retrieve the data of the raw material based on its key and join it with the list of raw material stocks. For example: The Raw Materials Stock document looks like this

{
    "factoryKey": "34",
    "quantity": "34",
    //  I want to fetch details such as name for this raw material key
    "rawMaterialKey": "-NDNPe47CDTbjmwGgW_3"
}

The Raw Material document looks like this

{
    "key": "-NDNPe47CDTbjmwGgW_3",
    "code": "R34",
    "name": "RAW2001"
}

Here's my Angular code:

import {Injectable, OnInit} from '@angular/core';
import {LocalStoreService} from '../local-store.service';
import {AngularFirestore} from '@angular/fire/compat/firestore';
import {Router} from '@angular/router';
import { RawMaterialStock } from '../../interfaces/raw-materials/raw-materiels-stock';
import {AngularFireDatabase, AngularFireList, AngularFireObject } from '@angular/fire/compat/database';
@Injectable({
  providedIn: 'root',
})
export class RawMaterialsStockService implements OnInit {

  rawMaterialsStocksRef: AngularFireList<any>;
  rawMaterialsRef: AngularFireList<any>;
  rawMaterialStockRef: AngularFireObject<any>;

  private dbPathStock = '/raw_material_stock';
  private dbPathRawMaterials = '/raw_material';

  constructor(
    private store: LocalStoreService,
    private router: Router,
    private afs: AngularFirestore,
    private db: AngularFireDatabase
  ) {

    this.rawMaterialsStocksRef = db.list(this.dbPathStock);
    this.rawMaterialsRef = db.list(this.dbPathRawMaterials);
  }

  ngOnInit(): void {
  }
  // Methods
  getRawMaterialStockList() {
    return this.rawMaterialsStocksRef.snapshotChanges(['child_added'])
      .subscribe(actions => {
        // WHAT SHOULD I DO HERE ????
      });
  }
}

I'd greatly appreciate any help with this problem. I seem to be stuck and unable to find any resources that address this specific issue!

Answer №1

When using snapshotChanges with AngularFire, you can leverage the power of rxjs to merge them into a single stream. It involves combining the snapshotChanges from both rawMaterialsStockref and rawMaterialsRef.

Follow these steps:

  1. Retrieve data from the raw material_stock collection.
  2. After fetching the stock data, retrieve a document from raw_material based on the field rawMaterialKey
  3. Merge this data with the raw_material_stock into one object.
  4. Finally, emit this combined object as an Observable stream.

For example:

this.rawMaterialsStockref =
      firestore.collection<any>('raw_material_stock');
    this.rawMaterialsRef = firestore.collection<any>('raw_material');

    this.rawMaterialsStockref
      .snapshotChanges(['added'])
      .pipe(
        switchMap((stockSnapshots) => {
          const stockWithRawMaterialsObservables = stockSnapshots.map((s) => {
            const stockId = s.payload.doc.id;
            const stock = s.payload.doc.data();

            return this.rawMaterialsRef
              .doc(stock.rawMaterialKey)
              .snapshotChanges()
              .pipe(
                map((rawMaterialSnapshot) => {
                  const rawMaterial = rawMaterialSnapshot.payload.data() ?? {};

                  return { ...rawMaterial, ...stock };
                })
              );
          });

          return combineLatest(stockWithRawMaterialsObservables);
        })
      )
      .subscribe((stocks) => {
        stocks.forEach((s) => console.log(s));
      });

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

Customizing number input types in Angular 2 - the perfect solution

Attempting to incorporate a time picker using HTML5 input type number in Angular2. The code snippet below illustrates the setup: <input type="number" [(ngModel)]="hour" (change)="checkHours();" name="one" min="1" max="12"> <input type="number" ...

What is the best way to combine various ngrx selectors together?

I currently have 3 selectors in my index.ts file export const selectDetails = createSelector( // some code ); export const selectTransactionResponse = createSelector( // some code ); export const selectAdditionalDetails = createSelector( // some code ); ...

There is a compatibility issue between the module and the engine "node" in this instance

Upon running the command npx create-react-app my-awesome-react-app --template typescript, I encountered the following yarn error: Error [email protected]: The engine "node" is incompatible with this module. Expected version "^6 || ^7 || ^8 || ^9 || ^10 || ...

Creating a conditional statement within an array.map loop in Next.js

User Interface after Processing After retrieving this dataset const array = [1,2,3,4,5,6,7,8] I need to determine if the index of the array is a multiple of 5. If the loop is on index 0, 5, 10 and so on, it should display this HTML <div class="s ...

Obtain non-numeric parameters from the URL in Angular 2 by subscribing to

How do I handle subscribing to a non-numeric parameter from a URL? Can the local variable inside my lambda function params => {} only be a number? Here's my code: getRecordDetail() { this.sub = this.activatedRoute.params.subscribe( ...

Stop displaying errors with Angular 6 HttpInterceptor

I am looking to implement an HTTPInterceptor to manage all Errors. Below is the code snippet I have written: return next.handle(req) .pipe( catchError((response: any) => { if (response instanceof HttpErrorResponse) { if (response.st ...

Creating a personalized validation function in Angular to validate a form field against another form field

Below is the TypeScript code for the EtcAddAuthorityComponent: export class EtcAddAuthorityComponent implements OnInit { // Code here... } The HTML code for the component is as follows: <h1 mat-dialog-title>Add Authority</h1> <div mat-di ...

typescript import { node } from types

Exploring the possibilities with an electron application developed in typescript. The main focus is on finding the appropriate approach for importing an external module. Here is my typescript configuration: { "compilerOptions": { "target": "es6", ...

How can an array of file paths be transformed into a tree structure?

I am looking to transform a list of file and folder paths into a tree object structure (an array of objects where the children points to the array itself): type TreeItem<T> = { title: T key: T type: 'tree' | 'blob' childr ...

Having trouble dispatching a TypeScript action in a class-based component

I recently switched to using this boilerplate for my react project with TypeScript. I'm facing difficulty in configuring the correct type of actions as it was easier when I was working with JavaScript. Now, being new to TypeScript, I am struggling to ...

Using React and Typescript: Populating an array within a For Loop using setTimeout is not happening sequentially or at all

I'm currently working on a function that animates images of random cars moving across the screen. My goal is to stagger the population of the "carsLeft" array using setTimeout, where I will eventually randomize the delay time for each car. Everything ...

The concept of Nested TypeScript Map Value Type

Similar to Nested Typescript Map Type, this case involves nesting on the "value" side. Typescript Playground const mapObjectObject: Map<string, string | Map<string, string>> = new Map(Object.entries({ "a": "b", &quo ...

The TypeScript compiler is generating node_modules and type declaration files in opposition to the guidelines outlined in the tsconfig.json file

For the past week, I've been trying to troubleshoot this issue and it has me completely puzzled. What's even more puzzling is that this app was compiling perfectly fine for months until this problem occurred seemingly out of nowhere without any c ...

Tips for including a sequelize getter in a model instance?

I'm currently struggling to add a getter to the name field of the Company model object in my project. Despite trying various approaches, I haven't had any success so far. Unfortunately, I also couldn't find a suitable example to guide me thr ...

Change to a different text field without the need to press the tab key by utilizing

I have set up three different input boxes and I want to know how to switch directly to the next text box without having to press the tab key on the keyboard. The values are stored in a variable called newStringPin. <input type="text" style="width: 38px ...

Delete an essential attribute from an entity

I am trying to remove a required property called hash from an object, but I keep encountering TypeScript or ESLint errors. All the properties of the interface are mandatory, and I do not want to make all properties optional using Partial. Here is the inte ...

Exploring the world of typed props in Vue.js 3 using TypeScript

Currently, I am attempting to add type hints to my props within a Vue 3 component using the composition API. This is my approach: <script lang="ts"> import FlashInterface from '@/interfaces/FlashInterface'; import { ref } from &a ...

Using a unique Angular module in various projects: A step-by-step guide

I am looking to develop a shared module that will house components such as login, sidebar, as well as pipes, services, and directives. @NgModule({ declarations: [ AppComponent, LoginComponent, SidebarComponent, InitialsPipe ], import ...

Monaco Editor in TypeScript failing to offer autocomplete suggestions

When using a union type as a parameter of a function in Monaco Editor, the suggestions do not appear. However, in VS Code, the suggestions are provided. Is there a setting I need to enable in Monaco to have the same functionality? Although Monaco provides ...

Guide for Deploying Firebase Function on Heroku for Google Assistant Integration

I have developed a straightforward function for Google Assistant (using Dialogflow) within a Firebase function with the following structure: functions/ node_module/ index.js package-lock.json package.json firebase.json I am looking t ...