0

I am working on a project that creates lines and I need to link each line with its corresponding marker on a Leaflet Map.

Sometimes, I am required to delete a line, hence I am required to delete a marker, and sometimes I need to interact with the marker directly.

For that purpose I added markerOptions and for testing purposes, I added a title, which I wish to alert, each time the marker is pressed.

On the creation method, I am able to access the title with no problems, the problem arise when I try to access the title from the onClick method.

I tried markerOptions.title; this.markerOptions.title; getMarkerOptions(title); this.getMarkerOptions(title), to no avail. I also looked at Leaflet website, and couldn't find an explanation how to achieve that. Additionally, I tried to send as a parameter to the onClick function the title, but apparently, the function does not accepts arguments besides the object that was clicked.

Below is my code for both methods.

Thanks in advance!

function addMarker(latitude, longitude, flightID) {
    const markerOptions = {
        title: markerIndex, //Naming the marker, according to the flightID
        clickable: true, //Allowing clicks on the marker
        draggable: false //Preventing dragging it.
    }

    const icon1 = L.icon({
        iconUrl: '../path',
        iconSize: [50, 32],
        iconAnchor: [25, 16],
        popupAnchor: [-3, -76]

    });


    markerID[markerIndex] = L.marker([latitude, longitude], //Initializing the marker with the cordinates of the flight.
        { icon: icon1 },
        markerOptions).addTo(myMap).on('click', onClick); // Adding the marker to the map.
    markerIndex++; //Generating a suffix for the next marker.

    currentMarkers.push(markerID[markerIndex-1]); //Pushing the marker to the list of markers.

    if ((highLightFlightID != null) && (highLightFlightID == flightID)) {
        boldFlight(flightID);
    }

    return markerIndex;


}



function onClick(e) {
    alert(this.markerOptions.title); //FAILS.
    alert(this.getLatLng()); //WORKS.
    highLightFlightID = null;

}
CUCUMBER
  • 63
  • 1
  • 10

1 Answers1

0

As documented in https://leafletjs.com/reference-1.6.0.html#class-options , all instances of Leaflet objects (that spawn from a class that inherits from L.Class, and that includes L.Marker) store options passed to its constructor into a options property.

Also note that the L.marker factory method takes parameters as...

L.marker(latlng, options)

...and not...

L.marker(latlng, options1, options2)

...so doing something like...

L.marker(
    [latitude, longitude],    
    { icon: icon1 },
    markerOptions
)

...will not work as you would expect.

Instead, you might want to use Object.assign()...

L.marker(
    [latitude, longitude],    
    Object.assign({ icon: icon1 }, markerOptions)
)

...or Leaflet's L.Util.extend polyfill...

L.marker(
    [latitude, longitude],    
    L.extend({ icon: icon1 }, markerOptions)
)

...or the spread operator...

L.marker(
    [latitude, longitude],    
    { icon: icon1, ...markerOptions }
)

...or, if icon1 is applied unconditionally to all markers, just make it part of your markerOptions inconditionally:

const markerOptions = {
    title: markerIndex,
    clickable: true,
    draggable: false,
    icon: L.icon({
      iconUrl: '../path',
      iconSize: [50, 32],
      iconAnchor: [25, 16],
      popupAnchor: [-3, -76]
    }
});
L.marker([latitude, longitude], markerOptions)

In any case, you can access the options property in an event handler (assuming that you passed the right options to the constructor, that is). Remember that the only parameter to a event handler attached to a Leaflet-specific event is a Leaflet-specific data structure, so:

function onMarkerClick(ev) {
  console.log(ev.target.options);
}

Since your question has a slight taint of XY problem (it's not really about options, it's about scope), I'll point out that you can forfeit storing data into a marker's options and use closures for the same effect.

Approaches vary: you may use anonymous functions in the scope where you're instantiating the markers...

function addMarker(latitude, longitude, flightID) {
  var marker = L.marker([latitude, longitude]);
  marker.addTo(map);
  marker.on('click', function() {  console.log(flightID); });
}

...or explicitly create closures by providing a function that, when called, will return a function to serve as the event handler (yes, the concept might be confusing)...

function addMarker(latitude, longitude, flightID) {
  var marker = L.marker([latitude, longitude]);
  marker.addTo(map);
  marker.on('click', getEventHandlerForId(flightID) );
}

function getEventHandlerForId(id) {
  return function(ev) {
    console.log(id);
  }
}
IvanSanchez
  • 18,272
  • 3
  • 30
  • 45