1

For this Angular project (I'm new to Angular --using angular8, I coded a lot on AngularJS but this is totally different) I have declared some global variables and I've created a leaflet map along with the leaflet.draw plugin. The map works perfect. When the event 'draw:created' is fired, I need access to one of those global variables, but instead I get an undefined error (check commented line on map-base.component.ts). What I'm doing wrong? I'm trying to follow the recommended practices and avoid the use of the 'window' object. Any idea very welcome. code:

global.ts

import { Injectable } from '@angular/core'
import * as L from 'leaflet';

@Injectable()
export class Globals {
    public L: any;
    public map: any;
    public enableFunc : boolean= true;
    public initZoom: any = 10;
    public initLatLng: any = [39.8, -75.5];
}

map-base.component.ts

import { Component, AfterViewInit } from '@angular/core';
import { Globals } from 'src/global'
import * as L from 'node_modules/leaflet/dist/leaflet-src.js'
import 'src/assets/js/leaflet.draw.1.0.4.min.js'

@Component({
    selector: 'map-base',
    templateUrl: './map-base.component.html'
})
export class MapBaseComponent implements AfterViewInit {
    [x: string]: any;

    constructor(private global: Globals) {
        this.global.L = L;
        L.Browser.touch = true;
    }
    ngAfterViewInit() {
       this.global.map = L.map('map', {}).setView(this.global.initLatLng, this.global.initZoom);
       L.tileLayer('https://cartodb-basemaps-d.global.ssl.fastly.net/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', { attribution: '© CartoDB' }).addTo(this.global.map);

       this.global.map.on('draw:created', function (e) {
           //this line return the object map
           console.log(this)
           //THIS LINE RETURNS ERROR
           console.log(this.global.initZoom);

       }
    }
}
BernieSF
  • 1,722
  • 1
  • 28
  • 42
  • 1
    At least "this" is the issue (pun intended!) https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-inside-a-callback – AT82 Nov 15 '19 at 20:17
  • 1
    @AJT82 totally solved my problem! Thanks! – BernieSF Nov 15 '19 at 22:01

2 Answers2

1

Thanks to the comment made by @AJT82, it was possible for me to solve the problem.

How to access the correct `this` inside a callback?

The solution was to use a lambda, so the context referenced by 'this' is the correct one.

   this.global.map.on('draw:created', (e) => {
       //this line return the object map
       console.log(this)
       //NOW THIS LINE RETURNS THE CORRECT VALUE
       console.log(this.global.initZoom);
   }
BernieSF
  • 1,722
  • 1
  • 28
  • 42
0

For Angular 2+, don't use the leaflet.js library directly. Instead, use the excellent ngx-leaflet package, which provides Angular-native bindings and wrappers for Angular. Follow the official instructions.

If you are new to Angular 2+, you might find it challening to make ngx-leaflet work initially, but it's totally worth it.

https://github.com/Asymmetrik/ngx-leaflet

ulmas
  • 2,203
  • 16
  • 22
  • I considered the use of ngx-leaflet, but unfortunately I use a ton of leafletjs plugins, and I need direct access to some of their features. Ngx wraps leaflet and expose a component, making things even more difficult. The code I provided here its just a very simplified section of my project. I suspect the event returns the map object instead of the global because leaflet is not part of the 'angular' world. I may be wrong. – BernieSF Nov 15 '19 at 19:27