1

Im having a Google Firestore collection called users which has the below format :

{
  "contactNumber":"0123456789",
  "email":"[email protected]",
  "location":[7.2906° N,80.6337° E],
  "isOnline":false,
  "name":"John"
}

the field location is in the geopint data type. Im fetching the users records in my service as below :

import { Injectable } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { User } from '../models/user';
import { Marker } from '../models/marker';

@Injectable({
  providedIn: 'root'
})
export class UserService {
    users: Observable<User[]>;
    markers:Marker[];

    constructor(firestore: AngularFirestore) {
       this.users = firestore.collection('users').valueChanges();
    }

    getUsers(){
       return this.users;
    }

    getUserMarkers(){

    }
}

the property users is now having the records as an Observable.

What i want to achieve here is, i have a separate model called Marker. I want to create an array of markers for each user record using the fields in the users records and return it from getUserMarkers function.

Marker model:

export interface Marker {
 name?:String;
 longitute?:Number;
 latitude?:Number;
 isOnline?:boolean;
}

longitute and latitude fields should be set using the location in user and other corresponding values ie name and isOnline. What would be the better way to do this?

Update :

Using one of the answers I came up with this.

 getUserMarkers() {
    return this.getUsers().pipe(map(users => {
         users.map(user => {
            return {
            name: user.name,
            longitute: user.location._long,
            latitude: user.location._lat,
            isOnline: user.isOnline
            }
        });
    })); 
 }

And from the component im trying to assign to this to a property like this.

export class MapComponent implements AfterViewInit {
@ViewChild("mapContainer", { static: false }) gmap: ElementRef;
map: google.maps.Map;
markers: Marker[];

constructor(private userService : UserService) {

  this.userService.getUserMarkers().subscribe(markers => {
     this.markers = markers;
   });
}

There its giving an error Type 'void' is not assignable to type 'Marker[]'. where im trying to assign the array to the property this.markers = markers; There

1 Answer 1

1

If you want to keep your array as an observable, you can add use the map function to format your data the way you want. The location might need some formatting to strip off the ° N, ° S, ° E, and ° W.

Observable

getUserMarkers() {
    return this.getUsers().pipe(map(users => {
         return users.map(user => {
            return {
                name: user.name,
                longitute: user.geopoint._long,
                latitude: user.geopoint._lat,
                isOnline: user.isOnline
            }
        });
    })); 
 }

If you want a pure array, you will need to declare a separate variable and possibly use the async/await meathods

separate variable

markerArray = [];
getUserMarkers() {
    this.getUsers().subscribe(markers => {
        this.markerArray = markers.map(user => {
          return {
            name: user.name,
            longitute: user.location[0]
            latitude: user.location[0]
            isOnline: user.isOnline
          }
        });
    }); 
}

async/await

async getUsers(){
    return this.users;
}

async getUserMarkers() {
    let markerArray = [];
    await this.getUsers().subscribe(markers => {
        markerArray = markers.map(user => {
          return {
            name: user.name,
            longitute: user.location[0]
            latitude: user.location[0]
            isOnline: user.isOnline
          }
        });
    }); 

    return markerArray;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Is it possible to return an Observable from getUserMarkers() ?
@jsb9009 yes, that should be the first option (return this.getUsers().pipe(map(user => {)
In your first option, its not possible to access the field Property 'name' does not exist on type 'User[]'.
sorry there was a compilation error so had to change as its viewed in the updated question. please have a look
@jsb9009 you were super close. you need to return your users.map(. I updated my answer and I apologize, I am dong this without checking my code because I don't want to spin up a new environment for this.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.