0

I am trying to make data from my dataservice to show on an openstreetmap as pinpoints.

When I try this with 1 pinpoint using static data, it works and the pinpoint shows. Now I want to use my dataservice to get an array of Parking objects and use them in my map to create those pinpoints. However I the pinpoints do not show and when I console log the parking from the loop in my map component it only shows the 1st one and the array shows to be undefined when I log it in the console.

The issue is that I am trying to call a method from a dataservice which returns an observable of an array of Parking objects. Now I want to loop throug the observable array to get each individual parking object from which I want to extract its longtitude and latitude to make it show on the map

I'm new to angular so I think this might have to do with the array that I receive being an observable, but no clue as how I would need to convert it to a normal array, I've tried adding a .subscribe without any luck

code map

  map;
  testp;
  vectorSource;
  vectorLayer;
  rasterLayer;
  features: Feature[];
  constructor(
    private _pds: ParkingDataService
  ) { }

  ngOnInit(): void {
    this.createParkPoints();
    this.vectorSource = new VectorSource({
      features: this.features
    });

    this.vectorLayer = new VectorLayer({
      source: this.vectorSource
    });
    this.initializeMap();

  }

  createParkPoints(){
    this._pds.allParkings$.forEach( (parkings: Parking[]) =>{
      parkings.forEach((parking: Parking) => {
        console.log(parking);
        let ftre: Feature = new Feature({
          geometry: new Point(fromLonLat([parseFloat(parking.longtitude), parseFloat(parking.latitude)]))
        });

        ftre.setStyle(new Style({
          image: new Icon(({
            color: '#8959A8',
            crossOrigin: 'anonymous',
            src: 'assets/park.svg',
            imgSize: [30, 30]`enter code here`
          }))
        }));

        this.features.push(ftre);
      })
    })
  }

  initializeMap(){
    this.map = new Map({
      target: 'map',
      layers: [ new TileLayer({
        source: new OSM()
      }), this.vectorLayer ],
      view: new View({
        center: fromLonLat([3.7219431, 51.054633]),
        zoom: 15,
      })
    });
  }

}

code dataservice

export class ParkingDataService {
  private _parkings$ = new BehaviorSubject<Parking[]>([]);
  private _parkings: Parking [];

  constructor(private http: HttpClient) {
    this._parkings$
    .pipe(
      catchError(err => {
        this._parkings$.error(err);
        return throwError(err);
      })
    )
    .subscribe((parkings: Parking[]) => {
      this._parkings = parkings;
      this._parkings$.next(this._parkings);
    });
   }

  get allParkings$(): Observable<Parking[]>{
    return this.parkings$;
  }

  get parkings$(): Observable<Parking[]>{
    return this.http.get(`${environment.apiUrl}/Parking`).pipe(
      tap(console.log),
      shareReplay(1),
      catchError(this.handleError),
      map((list: any[]): Parking[] => list.map(Parking.fromJSON))
    );

  }

  get parkings(){
    this.parkings$.subscribe(parkings =>{
      this._parkings = parkings as Parking[];
    });
    console.log(this._parkings);
    return this._parkings;
  }

  getParking$(id: number): Observable<Parking>{
    return this.http
      .get(`${environment.apiUrl}/Parking/${id}`)
      .pipe(catchError(this.handleError), map(Parking.fromJSON));
  }

  handleError(err: any): Observable<never> {
    let errorMessage: string;
    if (err.error instanceof ErrorEvent) {
      errorMessage = `An error occurred: ${err.error.message}`;
    } else if (err instanceof HttpErrorResponse) {
      console.log(err);
      errorMessage = `'${err.status} ${err.statusText}' when accessing '${err.url}'`;
    } else {
      errorMessage = err;
    }
    return throwError(errorMessage);
  }
}
JVK
  • 88
  • 2
  • 14
  • Not able to understand your problem, can you please make it more clear? Can you please add a stackblitz instance? – Jasdeep Singh Apr 06 '20 at 14:31
  • I don't think stackblitz would be any help as the data is fetched from a local hosted API and database. The issue is that I am trying to call a method from a dataservice which returns an observable of an array of Parking objects. Now I want to loop throug the observable array to get each individual parking object from which I want to extract its longtitude and latitude to make it show on the map – JVK Apr 06 '20 at 14:58
  • Does this answer your question? [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Igor Apr 06 '20 at 15:02
  • 1
    This question / problem can be solved with better understanding of how asynchronous calls work in javascript (and by extension typescript). Please read and study the answer in the aforementioned link. Asynchronous calls are a common and critical building block in writing/designing an application. It is critical that you understand how to work with asynchronous calls in javascript, and by extension typescript. Understanding these core concepts will help you become a better programmer and also ensure you do not keep "stubbing your toe" on the same problem. – Igor Apr 06 '20 at 15:03

1 Answers1

0

the service is returning an observable of type Parking[] (array of parkings)

so, to get that array of parkings, we need to subscribe to that observable just in the component

in the service we just need to return the obsrevable, and then subscribe to it in the component

we need a simple function in the service to load all the parkings from the server, without the need of all that getters you use in the service

so we can use some function like this in the service

in this function we will return the observable

loadAllParkings() {
    // here we will call the HTTP Request which returns an observable
    // you can omit this <Parking[]>, this refers to the return type of this http request, you can define this type in the map operator as you did before

    return this.http.get<Parking[]>(`${environment.apiUrl}/Parking`).pipe( // we are returning the observable here, so in the component we subscribe to this observable
        // do all the rxjs operators you need here
        // tap, map, catchError, ... and so on, as you need
    );
}

now we have an observable with type array of Parkings, so in the component, we just need to subscribe to that observable

in the component

createParkPoints () {
    // the function loadAllParkings in the service returns an observable, so we can do the subscription here
    this._pds.loadAllParkings().subscribe((parkings: Parking[]) => {
        // now you have the parkings array, loop over it
    });
}
Mohammed Yousry
  • 2,134
  • 1
  • 5
  • 7