What is the proper way to utilize RxJS to append a new property to every object within an array that is returned as an Observable?

I'm not very familiar with RxJS and I have a question. In an Angular service class, there is a method that retrieves data from Firebase Firestore database:

async getAllEmployees() { 
    return <Observable<User[]>> this.firestore.collection('users', ref => ref.where('profileType', '!=', 'admin')).valueChanges();          
  } 

The method returns an Observable containing User objects.

Here is the definition of the User interface:

export interface User {
    firstName: string;
    surname: string;   
    completeName: string;  
    email: string;
    photoUrl: string;
    phoneNumber: string;
    companyName: string;
    vatID: string;
    profileType: 'admin' | 'user' | 'unknown';    
    UID: string;    
    approved:boolean;
}

Now, I need to add the completeName field (which is not present in Firestore) to each object retrieved from the Observable array. I believe I can use the RxJS map operator for this. Here is what I tried:

return <Observable<Employee[]>> this.firestore.collection('users',ref => ref.where('isEmployee', '==', true)).valueChanges()
                                              .pipe(map(userObj => {

                                                        const completeObj = {
                                                          completeName: userObj["firstName"] + " " + userObj["surname"],
                                                          ...userObj
                                                        }
                                                        console.log("completeObj: ", completeObj);
                                                        return userObj;
                                                    }));

However, when I log the output, I see the following object created:

completeObj:  
{0: {…}, completeName: "undefined undefined"}
0: {firstName: "Andrea", isEmployee: true, socialSecurityCode: "NBLNDRH501O", password: "XXXXXX", isAdmin: false, …}
completeName: "undefined undefined"
__proto__: Object

It seems like the new calculated field is not being added to each object in the array returned by the Observable, but rather to the Observable itself. What am I missing? How can I correct this?

Answer №1

The data stored in your userObj variable represents an Array containing employee information. The rxjs operator map is used to manipulate arrays as a whole, not individual elements within the array. To achieve the desired outcome, you will need to implement a nested map function.

return <Observable<Employee[]>> this.firestore.collection('users', ref => ref.where('isEmployee', '==', true))
  .valueChanges().pipe(
    map(usersArr => usersArr.map(user => ({ ...user, completeName: user.firstName + " " user.surname}))),
  );

Answer №2

Initializing a property through assignment is not allowed.

Take a look at this example of an object:

{
  firstName: "Emma",
  lastName: "Smith"
}

The following syntax is incorrect:

{
  firstName = "Emma",
  lastName = "Smith"
} 

I'm amazed that it was compiled successfully. It could be related to the current context or 'this' keyword. When I attempted something similar, it didn't compile for me.

In addition, your map function should return a new object instead of the same value it receives.

return <Observable<Employee[]>> this.firestore.collection(
  'users',
  ref => ref.where('isEmployee', '==', true)
).valueChanges().pipe(
  map(userObj => ({
    ...userObj,
    completeName: userObj["firstName"] + " " + userObj["surname"]
  })),
  tap(completeObj => console.log("completeObj: ", completeObj))
);

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

Managing data from devices by using Ionic v2 along with the BLE Central plugin

Currently experiencing some difficulties when it comes to managing the device data of discovered peripherals. I am searching for some guidance on this matter. I can successfully scan for devices and my "success" callback functions without any issues. My g ...

Combining URLs in Angular 6 - A Step-by-Step Guide

How can I concatenate the commonUrl from CommonClass in Angular 6 for category.service.ts? common-class.ts export class CommonClass { constructor(public commonUrl : string = 'http://localhost:3000'){}; } category.service.ts import { CommonC ...

ESlint is unable to parse typescript in .vue files

After using vue ui to build my project, here is the content of my package.json: "@vue/cli-plugin-eslint": "^4.1.0", "@vue/cli-plugin-typescript": "^4.1.0", "@vue/eslint-config-standard": "^4.0.0", "@vue/eslint-config-typescript": "^4.0.0", "eslint": "^5.1 ...

Preserve the timestamp of when the radio query was chosen

I'm interested in finding a way to save the user's selected answer for a radio button question and track the time they saved it. Is there a way to achieve this using HTML alone? Or would I need to utilize another coding language or package? Just ...

React Component - Element with an undefined value

When I tried implementing an Ionic Modal as a React Component, I encountered the following error message: Type '({ onClose, tipo }: PropsWithChildren<{ onClose: any; tipo: number; }>) => Element | undefined' is not assignable to type & ...

Troubleshooting problems with contenteditable and input in Firefox and Safari on Angular 5

Currently, I am in the process of creating a table with cells that are editable. However, I am facing a challenge in updating the visual and typescript code simultaneously. I have explored various alternatives but unfortunately, none of them seem to work. ...

Encountering a SonarQube error message stating "Unnecessary 'undefined' should be removed" when using "undefined" as a function argument

When calling a function, I have been passing "undefined" multiple times as a parameter. However, the SonarQube report is flagging an error stating "Remove this redundant undefined". https://i.stack.imgur.com/YhOZW.png It should be noted that the function ...

Looking for assistance in correctly identifying types in react-leaflet for TypeScript?

Embarking on my 'first' project involving react-scripts-ts and react-leaflet. I am attempting to create a class that should be fairly straightforward: import {map, TileLayer, Popup, Marker } from 'react-leaflet'; class LeafletMap exte ...

What is preventing the combination of brand enums in Typescript 3?

Utilizing brand enums for nominal typing in TypeScript 3 has been a challenge for me. The code snippet below demonstrates the issue: export enum WidgetIdBrand {} export type WidgetId = WidgetIdBrand & string; const id:WidgetId = '123' as Wi ...

What are the limitations of using a JS file within an Angular application?

I am struggling to integrate some js methods from a file into an angular application. Unfortunately, the browser is unable to recognize the js file. I have tried following the guidelines in this SO post, but the browser still cannot locate the file in the ...

Monitoring the download status in the web browser: Angular 5

Currently, I'm in the process of developing an application that interacts with a REST API to download files. As per the API's behavior, it responds with the file immediately upon request. So, I've implemented the following logic to facilitat ...

Testing the angular unit for a partially functioning ternary condition

Can you help me troubleshoot an issue with my test case for a ternary function? It works fine for true conditions, but not for false ones. I'm not sure what's wrong with my logic. What changes should I make to fix it? public getData(ball: any) ...

Adding additional properties to Material UI shadows in Typescript is a simple process that can enhance the visual

https://i.stack.imgur.com/9aI0F.pngI'm currently attempting to modify the Material UI types for shadows, but encountering the following error when implementing it in my code. There is no element at index 25 in the tuple type Shadows of length 25. I&a ...

Decorating AngularJS' ExceptionHandler with TypeScript is not feasible because a function is not identified as such

Scenario: In the project I am currently involved in, there has been a transition from utilizing AngularJS (1.6.2) with JavaScript to TypeScript 2.1.5. We had implemented a decorator on the $exceptionHandler service which would trigger a call to a common ...

Custom options titled MUI Palette - The property 'primary' is not found in the 'TypeBackground' type

I am currently working on expanding the MUI palette to include my own custom properties. Here is the code I have been using: declare module '@mui/material/styles' { interface Palette { border: Palette['primary'] background: Pa ...

Circular dependency in Angular between two components

I'm currently working on an Angular 7 project that involves managing different entities, like Cars and Students. The structure of the application components can be represented by the following hierarchy: Cars Cars/CreateCar (dialog) Students Studen ...

Issue with Angular 12 service worker causing SW update to fail

I'm currently working on integrating a service worker into my Angular application to enable updates without user intervention. Here is the step-by-step process that I am following: Make changes to the application Run ng build Start an HTTP ser ...

Angular Kendo dropdownlist and input textbox are not working together as anticipated

I'm looking to implement a dropdown list similar to Google search using Kendo Angular. However, I've encountered an issue where entering text in the textbox and pressing "Enter" passes the first matching value from the dropdown list to my compone ...

Retrieve values from an async function with Ionic Storage

How can I retrieve the values of a token and user id that are stored in Ionic storage? Currently, I have implemented the following: auth.service.ts getToken() { return this.storage.get(TOKEN_KEY); } getId() { this.storage.get(ID); } crud.serv ...

Utilize localStorage.getItem() in conjunction with TypeScript to retrieve stored data

Within my codebase, I have the following line: const allGarments = teeMeasuresAverages || JSON.parse(localStorage.getItem("teeMeasuresAverages")) || teeMeasuresAveragesLocal; Unexpectedly, Typescript triggers an alert with this message: Argument ...