Search code examples
angulartypescriptrxjsrxjs-observables

How can I correctly use RxJS to add a new field to each object of an array returned into an Observable?


I am not so into RxJS and I ahve the following doubt.

Into this an Angular service class I have this method retrieving data from Firebase FireStore database:

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

As you can see it is returning an Observable of User object.

where User is this 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 (not presented on Firestore, so this field is not retrieved) that is the concatenation of the firstName and the surname field to each object of the retrieved array of the returned Observable. I am thinking that maybe I can use RxJS map operator to achieve this task. I was trying to do something like this:

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;
                                                    }));

But doing in this way I obtain that it is created the following object (I can see it in the console.log into my Chrome console):

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

So basically it seems to me that it is not adding this new calculated field to each object of the array returned as Observable but it is adding to the Observable itself.

Why? What is wrong? What am I missing? How can I fix it?


Solution

  • Your userObj is an Array of employees. The rxjs operator map maps this array, not the array elements. What you need is a "nested" map.

    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}))),
      );