Leaflet- Marker Click Event Works Fine But Methods of the Class Are Undefined in the Callback Function

Leaflet- marker click event works fine but methods of the class are undefined in the callback function

This is a classic JavaScript mistake.

this in JavaScript does not necessarily refer to your class instance object. It is the context of the function when it is called.

You can force this context with bind, and in many libraries you can easily force it as well. In this case with Leaflet you can pass a 3rd argument to on when attaching your event listener:

// Force current `this` to be the context when `this.markerClick` is called
marker.on('click', this.markerClick, this);

With bind it would be:

marker.on('click', this.markerClick.bind(this));

And there is also the arrow function solution, which uses the context / value of this where the arrow function is defined, rather than where it will be called:

marker.on('click', (event) => this.markerClick(event));

Angular 8 Leaflet put marker onclick

The problem is that you are using an anonymous function and in it's scope the this keyword doesn't reference to the leaflet map instance. You can avoid this by using an arrow function instead of the classic ES5 anonymous function beacause there are no binding of this in arrow functions.

private selectLocation() {

this.map.on('click', (e) => {
var coord = e.latlng;
var lat = coord.lat;
var lng = coord.lng;
console.log('You clicked the map at latitude: ' + lat + ' and longitude: ' + lng);

var mp = new L.Marker([lat, lng]).addTo(this.map);
alert(mp.getLatLng());
});
}

Using Prototypal Pattern with Creating a Leaflet Map: error with onEachFeature function

Much probably simply need to bind the this context when you pass your onEachFeature method as argument of your IIFE to build the callback to your AJAX call:

this.onEachFeature.bind(this)

See also Leaflet- marker click event works fine but methods of the class are undefined in the callback function

BTW you could also attach your click event listener directly on the Leaflet GeoJSON Layer Group instead of doing it for each child layer.

Leaflet cant display div when mouseover marker

Doing a quick search in Leaflet's source code will show that the only place that _controlCorners is accessed is at this line of code:

// @method addTo(map: Map): this
// Adds the control to the given map.
addTo: function (map) {
// [stuff]
var corner = map._controlCorners[pos];
// [stuff]
},

It seems that you're adding a control to a non-initialized map, or otherwise the parameter to the addTo() call is not a map. I suggest you start by console.log()ing the value of map in your calls to addTo(map).

geoJSON onEachFeature Mouse Event

You need to make sure that the right this is accessible in your callback. You do this using function.bind() in Javascript. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

constructor(private changeDetector: ChangeDetectorRef){}

fitBounds: LatLngBounds;
geoLayer = geoJSON(statesData, {
// Need to bind the proper this context
onEachFeature : this.onEachFeature.bind(this)
});

onEachFeature(feature , layer) {
// 'this' will now refer to your component's context
let that = this;

layer.on('click', <LeafletMouseEvent> (e) => {
that.fitBounds = [
[0.712, -74.227],
[0.774, -74.125]
];

// Aliased 'that' to refer to 'this' so it is in scope
that.changeDetector.detectChanges();
});

}

The let that = this trick is to make sure you don't have the same problem on the click event handler. But, you could also make that handler be a function in your class and use bind to set this.

Uncaught TypeError: Cannot read property 'lat' of undefined Leaflet and VueJS

Your onClick listener is called on Vue's @click="onClick" attribute of your DOM map container. Therefore it receives a plain "click" event, which does not have the Leaflet's latlng added property.

Since you want to do something on the map and not directly on its container, then you probably meant to listen to Leaflet's map "click" event. In that case, you can simply attach your listener with:

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

(you can attach it typically just after you initialize your map)

Note that it will greatly help you binding the this context by using the 3rd argument of Leaflet's on, otherwise this in your listener will refer to something else than your Vue component instance (see Leaflet- marker click event works fine but methods of the class are undefined in the callback function)

How can I create an ionic popover from a leafletjs polygon?

In your case you have a double context issue since you also pass your onEachFeature method that will get invoked with a this context that is already different from your class instance.

You could do onEachFeature: this.onEachFeature.bind(this) together with your layer.on("click", cb, this)

You could also use event delegation by attaching the listener on your GeoJSON Layer Group instead of each individual feature, so that you get rid of one of the context:

var geoJsonData = {  "type": "Point",  "coordinates": [2.35, 48.86]};
class Component { constructor(mapId) { this.myMap = L.map(mapId).setView([48.86, 2.35], 11);
L.geoJSON(geoJsonData).addTo(this.myMap).on("click", event => { console.log(event.target); // this is the GeoJSON Layer Group. console.log(event.layer); // this is the individual child feature. let popover = this.popoverCtrl.create('MyComponent'); popover.present(); }, this); // Not even needing the 3rd arg since you use a fat arrow function, which does not have its own context.
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors' }).addTo(this.myMap); }}
Component.prototype.popoverCtrl = { // Dummy popoverCtrl create(content) { dummyPopoverContent = content; return { present() { alert(dummyPopoverContent); }, }; },};
var dummyPopoverContent = '';
new Component('map');
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.1/dist/leaflet.css" integrity="sha512-Rksm5RenBEKSKFjgI3a41vrjkw4EVPlJ3+OiI65vTjIdo9brlAacEuKOiQ5OFh7cOI1bkDwLqdLw3Zg0cRJAAQ==" crossorigin="" /><script src="https://unpkg.com/leaflet@1.3.1/dist/leaflet-src.js" integrity="sha512-IkGU/uDhB9u9F8k+2OsA6XXoowIhOuQL1NTgNZHY1nkURnqEGlDZq3GsfmdJdKFe1k1zOc6YU2K7qY+hF9AodA==" crossorigin=""></script>
<div id="map" style="height: 180px"></div>


Related Topics



Leave a reply



Submit