Leaflet - Toggle Layers

I am attempting to reproduce this example to enable a control that toggles on and off different layers:


But while my code looks to be identical, I am getting very different behavior in Observable:

Specifically, the example has the layers enabled by default, whereas the Observable examples (using either Tom or Mike’s templates) do not. Also, once I toggle on or off a control, that’s it – I can’t keep clicking the button to make the layers appear and disappear.

I’ve had a look through the many Leaflet maps on Observable but have not found something to help identify a solution.

And a final bit of confusion: when I change the .setView coordinates, I no longer get a working tile layer. Maybe it’s just my Internet connection - or do you see the same?

Any insights?

… I found that the toggles begin to ‘work’ after more than one option is added. It appears that the default behavior of the toggle is ‘toggle between’ rather than toggle on/off–allowing me to select to show this or that layer group (or that’s at least how it’s working in the updated version of the notebook above.

I suppose I’ll have to work more with layer events / methods?

What I find odd is that I somehow managed to get the toggles working correctly in another notebook that uses older versions of Leaflet, but as I de-construct that working notebook and try to build it back to reflect the official leaflet example, I end up with the same buggy menu.

… And for whatever reason, the particular tile layer and coordinates aren’t loading across three separate devices in my home! Yet if I change the coordinates to Mike’s original NYC reference and zoom level, it’s fine. Perplexing.

After some further tinkering, I got the effect working. If anyone would be willing to clarify for me why / how this approach is different (and functional) to my first notebook, that’d be amazing!

… The toggle controls ‘magically’ started working after I made the following changes:

  1. [definitely unrelated] I changed out the base time so that I could finally see Denver (the other one still wouldn’t load past zoom level 7 after 3 days)
  2. [probably unrelated] I required an additional leaflet.js from ESRI to allow me to display their base tiles
  3. [probably related] I changed the way controls are added to the map, as follows:
  let baseLayers = {
       "Open Street Maps":osmLayer,
       "World Imagery":world_imagry,
       "World Topo Map":world_topo, 
  let controlLayers = {
		"Cities": cities,

  let c_layers = new L.control.layers(baseLayers, controlLayers,{position:'topright',collapsed:false})


With this, one can toggle on/off a single layer (rather than toggle between).

What I find intriguing is that functionality appears different with the inclusion of the multiple basemap option (which the example also included). I had not expected that it would require basemap options to be able to toggle on/off a particular layer.

Hi @aaronkyle, I may not be able to help you much than by playing happily to be your duck.
I did not do any notebook with maps. So let me just describe what I see from my firefox on linux for your last notebook.

On open/ refresh,

  • I seen open street map and I can toggle on and off the cities -> no problem,
  • I toggle to World imagery, -> no problem,
  • I toggle cities on and off, one time -> no problem,

But then…

  • I toggle them a second time, -> nothing change, problem

I continue from world imagery selected, cities toggled off after above bug…

  • I select World topo map, nothing change, -> problem. I should see the world topo map.
  • I click the city toggle button, the World topo map appears with no cities toggles -> problem why is the topo map apearing after I click the city toggle button. Why are the no city markers displayed?
  • I insist and try to toggle the cities several times. --> nothing change.
1 Like

Thanks @maliky!

The duck method looks good! For practice, I might go back to both notebooks and comment in each line to clearly state to myself what is happening. I also appreciate your point that I should try more of my own debugging with the console. Mike has reminded me to do this at least a couple of times; I apologize for being slow to internalize!

For now, here’s my play-by-play, inspired by yours:

Notebook 1 Original

Context: After forking from ‘Hello Leaflet’ by Mike, followed online example for layer controls, but did not use additional option for base layers.

Run notebook:

  1. At initialization → Map tile does not load. :x:
  2. At initialization → Layer control visible; markers not displaying. :x:
  3. Pressing layers button → markers appear. :white_check_mark:
  4. Pressing layers button again → markers do not disappear; toggle stays activated. :x:

Notebook 2 Forked

Context: Forking from notebook 1, I compare with another notebook I had where layer toggles were working, making the changes noted earlier in my previous thread post.

  1. At initialization → Map tiles load. :white_check_mark:
  2. At initialization → Layer control visible; markers displaying. :white_check_mark:
  3. Pressing layers button → markers disappear; toggle dis-activates. :white_check_mark:
  4. Pressing layers button again → markers re-disappear; toggle re-activates. :white_check_mark:

… The issue I will continue to investigate with the console as a next learning tool will be to learn why I am seeing apparently different behaviors with and without the base tile layers.

Thanks for your encouragement!!

@aaronkyle, It was not my intent to make you think you should do more on your own. I myself find the rubber duck not realistic enough. Because for the method to work at its best you have to think how the other will think about what you are saying and … the rubber ducker obviously do not think. So I just wanted to tell you that what you report here is read and thought about by real humans. I’m been a duck here because I won’t be able to tell you why it is not working (no experience with maps) but I will acknowledge if I understand what you report.

I am coming back in a few hours to check your notebook again…
… a few hours later:
Here’s my use case to break the your notebook :slight_smile:

This generate the folowing error in chromium

leaflet.js:5 Uncaught TypeError: Cannot read property 'parentNode' of null
    at li (leaflet.js:5)
    at i._removeIcon (leaflet.js:5)
    at i.onRemove (leaflet.js:5)
    at i.removeLayer (leaflet.js:5)
    at i.eachLayer (leaflet.js:5)
    at i.onRemove (leaflet.js:5)
    at i.removeLayer (leaflet.js:5)
    at i.eachLayer (leaflet.js:5)
    at i.onRemove (leaflet.js:5)
    at i.removeLayer (leaflet.js:5)

Not sure what the reason is, maybe you should try with only one city and one extra layer.

1 Like