leafletngx-leaflet

ERROR TypeError: Cannot read property '_leaflet_pos' of undefined


I have angular 10 app using ngx-leaflet and routing. I have a map component, which dynamically displays custom markers on map, based on user selection. I navigate from map component view to another component. Then I navigate back to map component. User can change date, and based on that, old layer of markers is removed and new layer of markers is loaded and shown. Everything works fine, but I always get this error:

ERROR TypeError: Cannot read property '_leaflet_pos' of undefined
at getPosition (leaflet-src.js:2450)
at NewClass._getMapPanePos (leaflet-src.js:4439)
at NewClass._moved (leaflet-src.js:4443)
at NewClass.getCenter (leaflet-src.js:3798)
at NewClass.setZoom (leaflet-src.js:3181)
at SafeSubscriber._next (map.component.ts:960)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)

I can reproduce this error only when I go back to the map component. If i stay only at the map component no error is shown. I've searched for fix, but from what I found it seems nobody really knows why is this happening and how to fix this error. I've found these two issues on GitHub dealing with the same problem in Vue.js, so I guess it's problem with leaflet itself, and not ngx-leaflet.

https://github.com/vue-leaflet/Vue2Leaflet/issues/613

https://github.com/stefanocudini/leaflet-search/issues/129

I've tried to change this:

  function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance

return el._leaflet_pos || new Point(0, 0);

}

to this:

 function getPosition(el) {
// this method is only used for elements previously positioned using setPosition,
// so it's safe to cache the position for performance

if(el){
    return el._leaflet_pos || new Point(0, 0);
    }
    else{
    return new Point(0, 0);
    }

}

But then the error just looks like this:

ERROR TypeError: Cannot set property '_leaflet_pos' of undefined
at setPosition (leaflet-src.js:2433)
at NewClass._resetView (leaflet-src.js:4154)
at NewClass.setView (leaflet-src.js:3174)
at NewClass.setZoom (leaflet-src.js:3186)
at SafeSubscriber._next (map.component.ts:960)
at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
at SafeSubscriber.next (Subscriber.js:122)
at Subscriber._next (Subscriber.js:72)
at Subscriber.next (Subscriber.js:49)
at MapSubscriber._next (map.js:35)

UPDATE: As @pk. suggested in comments ,when I don't call setZoom or call it before I remove old markers I get this error:

ERROR TypeError: Cannot read property 'appendChild' of undefined
at NewClass._initIcon (leaflet-src.js:7608)
at NewClass._initIcon (leaflet.rotatedMarker.js:23)
at NewClass.onAdd (leaflet-src.js:7460)
at NewClass._layerAdd (leaflet-src.js:6572)
at NewClass.whenReady (leaflet-src.js:4433)
at NewClass.addLayer (leaflet-src.js:6634)
at NewClass.eachLayer (leaflet-src.js:6861)
at NewClass.onAdd (leaflet-src.js:6845)
at NewClass._layerAdd (leaflet-src.js:6572)
at NewClass.whenReady (leaflet-src.js:4433)

UPDATE 2: When I don't add new marker layer to map (this.deskLayer.addTo(map)), the error dissapears, but I want to add new markers to map... This is what happens when user changes date:

onMapReady(map: Map) {

//listening for USER DATE CHANGE
this.userFloorService.sharedUserSelectedDate
  .pipe(skip(1))
  .subscribe(() => {
    this.deskLayer.remove(); // first remove old desks
    this.userFloorService // then get desks and reservations
      .getFloor(this.floorNumber)
      .subscribe( (data) => { 
        // create new reservations
        let reservationsArr = data.records[0].reservations;
        // create new DESKS
        let deskMarkers = [];
        data.records[0].desks.forEach((desk) => {
          let deskId = desk.desk_id;
          let deskMarker = marker(
            [
              desk.desk_coordinate.coordinates[0],
              desk.desk_coordinate.coordinates[1],
            ],
            {
              title: this.getDeskTitle(desk, reservationsArr), // set desk title to RESERVED/FREE
              rotationAngle: desk.desk_angle,
              rotationOrigin: 'center center',
              riseOnHover: true
            }
          ).on('click', () => {
            this.zone.run(() => {
              this.openDeskDialog(deskMarker.options.title,deskId); 
            });
          });
          deskMarker.setIcon(this.getDeskIcon(deskMarker)); // for displaying desk icons on zoomLvl -1.5
          deskMarkers.push(deskMarker);
        });
        this.deskLayer = layerGroup(deskMarkers); // add new desks to deskLayer
        this.layersControl.overlays['Desks'] = this.deskLayer; // reassign desks in overlays for correct desk layer toggling 

        this.deskLayer.addTo(map); 
        map.setZoom(-1); // set zoom
      },
      error =>{
        console.log(error);
      }
      ); 
  });

Solution

  • It turned out, that these errors were happening because I used BehaviorSubject to pass data between components, and everytime I navigated out and back to the map component, new subscription to BehaviorSubject was created without destroying the old subscribtion. So destroying subscriptions everytime I navigated from map component solved it. Maybe this will help to somebody.