2

I fiddeld together some angular 8 app that uses the leaflet library. I ended up with some working code but feel it might not be the best way to achieve what i wanted. Please read until the end first...

My component typescript file looks like this:

import { Component, OnInit } from '@angular/core';

declare let L;

@Component({
  selector: 'app-new-hotspot-form',
  templateUrl: './new-hotspot-form.component.html',
  styleUrls: ['./new-hotspot-form.component.css']
})
export class NewHotspotFormComponent implements OnInit {

  latitude: string = "51.505";
  longitude: string = "-0.09";
  name: string = "Hotspot 1";
  radius: string = "5.0";
  map: any;

  constructor() { }

  getOnMapClickHandler() {
    const myComponent = this;
    let clickHandler = function(e) {
      myComponent.latitude = e.latlng.lat;
      myComponent.longitude = e.latlng.lng;
      myComponent.map.setView([e.latlng.lat, e.latlng.lng]);
    };
    return clickHandler;
  }

  ngOnInit() {
    this.map = L.map('newhotspot').setView([this.latitude, this.longitude], 13);
    this.map.on('click', this.getOnMapClickHandler());

    L.tileLayer('https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}.png?access_token={accessToken}', {
        attribution: 'Map data &copy; <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
        maxZoom: 18,
        id: 'mapbox.streets',
        accessToken: '_MY_SECRET_ACCESS_TOKEN_'
    }).addTo(this.map);

  }

}

And the corresponding html file like this:

<div class="ui-fluid">

  <div class="ui-g">

    <div class="ui-g-12 ui-md-6">

      <div class="ui-g-4">
        Name
      </div>

      <div class="ui-g-8">
        <input [(ngModel)]="name" pInputText type="text" />
      </div>

    </div>

    <div class="ui-g-12 ui-md-6">

      <div class="ui-g-4">
        Radius
      </div>

      <div class="ui-g-8">
        <input [(ngModel)]="radius" pInputText type="text" />
      </div>

    </div>

    <div class="ui-g-12">

      <div class="ui-g-2">
        Location
      </div>

      <div class="ui-g-10">
        <div id="newhotspot"></div>
      </div>

    </div>

    <div class="ui-g-12 ui-md-6">
      <div class="ui-g-4">
        Longitude
      </div>
      <div class="ui-g-8">
        <input [(ngModel)]="longitude"  type="text" />
      </div>
    </div>
    <div class="ui-g-12 ui-md-6">
      <div class="ui-g-4">
        Latitude
      </div>
      <div class="ui-g-8">
        <input [(ngModel)]="latitude" pInputText type="text" />
      </div>
    </div>

  </div>

</div>

primeng is also "in the boat" but does not play a role for this question (I hope...).

I was assigning an event handler to my map's click event and was wondering why the data binding that i do was not working. Until i found out that my event handler does not have this assigned to my component. I than changed my code to do a factory method that binds this somehow. Even though the code works now I have some strang gut feeling about it and was wondering if there is a more native way to achive that the event handler is working correcly

Matthias
  • 3,458
  • 4
  • 27
  • 46

1 Answers1

1

As AJT82 suggested, fat arrow function syntax should give you what you are looking for, e.g changing

this.map.on('click', this.getOnMapClickHandler());

To

this.map.on('click', (e) => {
  this.latitude = e.latlng.lat;
  this.longitude = e.latlng.lng;
  this.map.setView([e.latlng.lat, e.latlng.lng]);
}

Then you will be able to remove getOnMapClickHandler.

brian3kb
  • 291
  • 2
  • 4