I want to add a button to an L.control() infobox in a leaflet map. Nevermind what the original intent of the button was, now I just want to know why this does not work (info.buttonClicked()
is not called when the button is clicked):
let map;
map = L.map("map").setView([45.0, 0.0], 8);
var tiles = L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
maxZoom: 19,
}).addTo(map);
let info = L.control();
info.onAdd = function (map) {
this._div = L.DomUtil.create("div", "info");
var button = L.DomUtil.create('button', 'close-btn', this._div);
button.innerHTML = 'x';
button.style.float = 'right';
button.addEventListener('click', function() {
console.log('buttonClicked event');
info.buttonClicked();
});
this._div.innerHTML += "some info";
return this._div;
};
info.buttonClicked = function() {
console.log('info.buttonClicked() called');
//this._div.innerHTML += '';
};
info.addTo(map);
(full example here), whereas this works (rest of the code is the same):
info.onAdd = function (map) {
this._div = L.DomUtil.create("div", "info");
this._div.innerHTML = '<button style="button" onclick="info.buttonClicked()" id="minimize-btn">x</button>';
this._div.innerHTML += "some info";
return this._div;
};
In the first case I don’t see any error messages but nothing happens. Why?
NOTE: adding L.DomEvent.disableClickPropagation(this._div);
, as suggested in one of the answers below, doesn’t fix this.
2
Answers
The culprit is the line:
It destroys (and then recreates) all child elements of
this._div
so the event listener associated with the originalbutton
is lost.If you replace this line with say:
the button will work as intended.
The issue arises because Leaflet’s L.DomEvent system intercepts events on the map and might prevent events from propagating to elements added to the map’s controls or layers. Specifically, when using L.DomUtil.create() to create elements and appending them to the map’s DOM, Leaflet might block or modify the default event behavior, such as click.
To resolve this issue, you need to ensure the event properly propagates and is not being stopped by Leaflet’s event-handling system.
Here’s how to fix your code:
Key Fixes and Explanations:
Disable Click Propagation:
The line L.DomEvent.disableClickPropagation(this._div); ensures that clicks on the info control (including the button) don’t propagate to the map. Without this, Leaflet might treat clicks as map interactions, interfering with your button’s event handling.
Event Listener:
Use a standard button.addEventListener("click", …) to bind the click event to the button. This works fine as long as disableClickPropagation is in place.
Remove Control:
The info.buttonClicked() method demonstrates how you can use the removeControl() method to remove the control when the button is clicked.
Testing:
Place this code in your project and verify that the button is functional.
Open the browser console and confirm that clicking the button logs the appropriate messages and removes the control from the map.