agm markers not rendering from ngfor
Asked Answered
T

2

8

I am fairly new to angular and have what I think is a basic problem.

I create my map like

<agm-map [latitude]="lat" [longitude]="lng">
    <agm-marker [latitude]="location.lat" [longitude]="location.lng" *ngFor="let location of locations; let i=index">
        <agm-snazzy-info-window [maxWidth]="200" [closeWhenOthersOpen]="true">
            <ng-template>
                <strong>{{location.title}}</strong>
                <p>adresse</p>
            </ng-template>
        </agm-snazzy-info-window>
    </agm-marker>
</agm-map>

when I set markers manually, everything works, but when I use *ngFor to loop through my list, the html for the markers is created, but apparently after the script for the map looked for markers, so no markers are rendered (the map itself is).

From my controller:

export class LocationMapComponent implements OnInit {

 lat: number = 51.678418;
 lng: number = 7.809007;
 locations: Location[];

 async ngOnInit() {

}

public async getLocations()  {
    this.locations = await this._locationService.getLocations();

}

constructor(private _locationService:LocationService, private _coreCOMService: CoreCOMService, private _coreLanguageService: CoreLanguageService, private _coreLogService: CoreLogService, private _componentFactoryResolver: ComponentFactoryResolver, private _coreSystemService: CoreSystemService) {

    this.getLocations();
}

}

the locations get loaded from a service which fetches them from a remote database. I do believe the problem is that the map is rendered before the ngFor loop is executed, I am not sure how I can make sure the loop is executed first OR how to tell the map to (re-)render the marker only after the loop is done.

As said, this is probably pretty basic, but I am at a loss right now, thanks.

Torras answered 27/10, 2017 at 9:51 Comment(3)
I'm having the exact same issueHoskins
Are the lat / lngs for the locations array typed as Number? I had a similar issue with the latlng being returned from an API as strings.Phyllous
@Phyllous It was a string indeed. I changed it to number and now it works. Which buffles me a bit, to me it looks like it should not matter since the lat und lng is only pasted into the html and thus it should not matter whether it is a string or a number, right? p.s. You should make this into an answer so I can check it.Torras
P
13

The Latitude/Longitudes must be of type Number. If they are being returned from an API or some kind of service as a string they need to be converted. From my experience it seems to require it to be strictly typed as a Number.

Phyllous answered 22/11, 2017 at 12:14 Comment(2)
Wtf. This made my day. Thanks!Trinitarianism
Exactly the words that came to my mouth.Ostrich
T
0

I need to solve the problem that I have with ngFor when it comes to displaying the markers.

I collect the data from an API, (latitude, longitude) and I can not do binding.

I suspect that it may be because it does not detect the type as 'number'.

map.interface.ts:

export interface Marker {
    lat: number[];
    lng: number[];
 }

map-location.ts:

import { CapacitorBanksService } from '../../services/capacitorBanks.service';
import { Component, OnInit} from '@angular/core';
import { AuthService } from '../../services/auth/auth.service';
import { Marker } from './map.interface';

@Component({
  selector: 'mdb-map-location',
  templateUrl: './map-location.component.html',
  styleUrls: ['./map-location.component.scss'],
  providers: [AuthService, CapacitorBanksService]
})

export class MapLocationComponent implements OnInit {

  localCustomer = localStorage.getItem('customer_id');
  subscriptions: any;

  latitude: number = 40;
  longitude: number = 0;

  lat: number[] = [];
  lng: number[] = [];

  markers: Marker[] = [{
    lat: this.lat,
    lng: this.lng,
}];

  constructor(public authService: AuthService, public cbank: CapacitorBanksService) { }

  ngOnInit(): void {

    this.cbank.getCapacitorBanks(this.localCustomer).subscribe(ires => {
      let data: any;
      data = ires.data;

      data = data.map(index => {
        return index.id.id;
      });

      let indexx = 0;
      const interval = setInterval(() => {
        if ( data[indexx] ) {
          this.subscriptions = this.cbank.getAssetAttributesServer(this.localCustomer, data[indexx]).subscribe(vres => {

            const myObj = vres;

            Object.keys(myObj).forEach(key => {
              if (myObj[key].key === 'latitude') {
                  this.lat.push(myObj[key].value);
              }
            });

            Object.keys(myObj).forEach(key => {
              if (myObj[key].key === 'longitude') {
                  this.lng.push(myObj[key].value);
              }
            });
            indexx ++;
          });
        } else {
          this.subscriptions.unsubscribe();
        }

        if ( indexx >= data.length - 1 ) {
          clearInterval(interval);
        }
      }, 400);
      console.log('COORD: ', this.markers);

    });
  }

}

And this is map-location.component.html:

<div id="content">
    <agm-map [latitude]="latitude" [longitude]="longitude" [zoom]="6">
        <agm-marker-cluster>
            <!-- <agm-marker *ngFor="let marker of markers; let i=index" 
            <agm-marker *ngFor="let marker of markers; let i=index" [latitude]="marker.lat[i]" [longitude]="marker.lng[i]"></agm-marker>
        </agm-marker-cluster>
    </agm-map>
</div>

This is a console.log of the array

Taconite answered 12/6, 2018 at 9:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.