Search code examples
javascriptangularleaflet

How to work with leaflet polyline's context menu


In Angular application, using "leaflet": "^1.9.4" and "leaflet-contextmenu": "^1.4.0", I draw a graph where nodes are connected by sections. For nodes I create markers

const options = {
  contextmenu: true,
  contextmenuInheritItems: false,
  contextmenuItems: this.buildMarkerContextMenu()
};
const marker = L.marker(coordinate, options);
(<any>marker).id = node.id;

for sections I create lines

const options = {
  contextmenu: true,
  contextmenuInheritItems: false,
  contextmenuItems: this.buildSectionContextMenu()
};
const line = L.polyline([coors1, coors2], options);
(<any>line).id = section.id;

After adding all nodes and sections I can iterate through map's layers and see all nodes(markers) and sections(polylines) with their ids successfully.

Then in contextmenu callbacks for node

static showInformation(e: L.ContextMenuItemClickEvent) {
    console.log(e.relatedTarget);
    console.log((<any>e.relatedTarget).id);
}

all works properly, I get the node I clicked on.

Whereas for section I see the contextmenu, I can click menu items and get to their handlers but the same code somehow does not work: e.relatedTarget is undefined

static showSectionInformation(e: L.ContextMenuItemClickEvent) {
    console.log(e);
    console.log(e.relatedTarget); // !!! undefined
    //console.log((<any>e.relatedTarget).id);
}

All examples of leaflet-contextmenu show how to create menu for map and markers. Maybe for polyline something should be done differently?


Solution

  • It is hard to say whose fault it is - leaflet or leaflet.contextmenu. When context menu clicked on polyline two events are fired: from polyline itself and from map. For marker all done great - only marker's event is fired. So the solution for polyline is to add (beside context menu) a handler of 'contextmenu' to the polyline where stop event propagation.

    const options = {
      contextmenu: true,
      contextmenuInheritItems: false,
      contextmenuItems: this.buildSectionContextMenu()
    };
    const line = L.polyline([coors1, coors2], options);
    line.on('contextmenu', (e) => {
      L.DomEvent.stopPropagation(e);
    });
    

    That is it.