The methods L.layerGroup.addLayer() and L.layerGroup.removeLayer() allow you to add and remove markers. The names of these methods was confusing to me because you are not adding or removing a layer, but rather markers in a layer.
That aside, the removeLayer() does not work too well when you want to dynamically remove markers from the layer control because you can’t find the marker in the control. Leaflet does add an id to each marker, but it is done internally and you don’t know what that id is.
I solved this problem by adding my own id in the options of the marker creation line, like this:
marker = L.marker([y,x],{icon:crowRed14Icon,myId:id}).bindPopup(content);
myId:id refers to the id of the record in my MySQL table that represents the marker.
Now when I want to find the markers in the layer control, I loop through them and find myId, like this:
for(key in lyrCrowTrax._layers)
{
myId = lyrCrowTrax._layers[key].options["myId"];
If the marker exists in the new markers that come from the Ajax lookup, I leave it in the layer control. If it is not in the new markers it means that the user has panned or zoomed the map away from the marker, and I remove the marker from the layer control, like this:
markerToRemove = lyrCrowTrax._layers[key];
// Use the API as it does other things to remove the marker from the map
lyrCrowTrax.removeLayer(markerToRemove);
I hope that the leaflet team will add a public method to access a marker in the layer control by an id field. Then I wouldn't have to write code that accesses the internal code of leaflet.js, which may change at some point and break my code.
The whole code, starting from the success callback function of the ajax lookup, is below, and you can see the whole web map application at http://giscourses.net/crowtrax/crowtrax.html.
function updateMarkersSuccess(data)
{
var objNewMarker={}; // container for the new markers
var arMarker = []; // only used the first time to initialize lyrCrowTrax
for(key in data)
{
var id = data[key].id;
var x = data[key].x;
var y = data[key].y;
var aggressiveness = data[key].aggressiveness;
var description = data[key].description;
var date_entered = data[key].date_entered;
content = "<b>Aggressiveness</b>: " + aggressiveness + "<br>" +
"<b>What happened</b>: " + description + "<br>" +
"<b>Date</b>: " + date_entered;
numberPoints++;
if (isNaN(x) || isNaN(y))
{
continue;
}
var dictXY = {lat: y, lng:x, count: 1};
arHeatmapPoint.push(dictXY);
//$("#debug").append("x: " + x + ", y: "+ y + "<br>");
marker = L.marker([y,x],{icon:crowRed14Icon,myId:id}).bindPopup(content);
//Put all of the new markers into an object with the database id as a key;;
objNewMarker[id] = marker;
arMarker.push(marker);
}// end for
// Test if lyrCrowTrax is null and do this only one time
if(lyrCrowTrax == null)
{
lyrCrowTrax = L.layerGroup(arMarker).addTo(map);
return;
}
// Now loop through lyrCrowTrax and extract the database ids
for(key in lyrCrowTrax._layers)
{
myId = lyrCrowTrax._layers[key].options["myId"];
// Test if this id is also the key in objNewMarker
// If it is, delete it from objNewMarker
// If it is not, delete it from lyrCrowTrax
if(myId in objNewMarker)
{
delete objNewMarker[myId];// No API call here, just delete the marker
}
else
{
markerToRemove = lyrCrowTrax._layers[key];
// Use the API as it does other things to remove the marker from the map
lyrCrowTrax.removeLayer(markerToRemove);
}
}
// Now add the remaining markers in objNewMarker to lyrCrowTrax
for (myId in objNewMarker)
{
lyrCrowTrax.addLayer(objNewMarker[myId]);
}
}// end updateMarkersSuccess