rstudio / leaflet

R Interface to Leaflet Maps

Home Page:http://rstudio.github.io/leaflet/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Permanently deleting a legend attached to a group

dfriend21 opened this issue · comments

I've been trying to delete a legend permanently from a leaflet map in a shiny app. In my particular case the legend is attached to a specific group. When I use removeControl() (or clearControls()) the legend is removed, but if you toggle the layer off and then on the legend reappears. However, I want the legend to be removed permanently.

I've made a small shiny app to demonstrate.

To reproduce:

  1. Click the "Remove legend" button (legend should disappear)
  2. Using the layer control on the map, turn the "polygons" layer off and then back on again - the legend will re-appear.
library(leaflet)
library(shiny)
library(terra)

shp_path <- system.file("ex/lux.shp", package="terra")
v <- vect(shp_path)
e <- ext(v)
e <- unname(as.vector(e))

ui <- fluidPage(
  leafletOutput("map"),
  div(actionButton("add_legend", "Add legend")),
  div(actionButton("remove_legend", "Remove legend"))
)

server <- function(input, output) {
  output$map <- renderLeaflet(
    leaflet("map") %>%
      fitBounds(lng1 = e[1], lat1 = e[3], lng2 = e[2], lat2 = e[4]) %>%
      addTiles(group = "Streets") %>%
      addLayersControl(overlayGroups = "polygons", position = "topright",
                       options = layersControlOptions(collapsed = FALSE)) %>%
      addPolygons(data = v, group = "polygons") %>%
      addLegend(pal = colorFactor(rainbow(5), v$ID_2),
                values = v$ID_2,
                group = "polygons",
                layerId = "polygons_legend",
                title = "legend")
  )

  observeEvent(input$add_legend, {
    leafletProxy("map") %>%
      addLegend(pal = colorFactor(rainbow(5), v$ID_2),
                values = v$ID_2,
                group = "polygons",
                layerId = "polygons_legend",
                title = "legend")
  })

  observeEvent(input$remove_legend, {
    leafletProxy("map") %>%
      removeControl(layerId = "polygons_legend")
      # clearControls() # also doesn't work
  })
}

# Run the application
shinyApp(ui = ui, server = server)

I've done some searching the web to see if I could find a solution, but I've come up empty.

I've done some digging in the code, and I'm pretty sure I know why it's happening. In methods.js there is the following code in addLegend() - this particular chunk of code only runs when a group name has been provided:

    map.on("overlayadd", function(e){
      if(e.name === options.group) {
        map.controls.add(legend, options.layerId);
      }
    });
    map.on("overlayremove", function(e){
      if(e.name === options.group) {
        map.controls.remove(options.layerId);
      }
    });
    map.on("groupadd", function(e){
      if(e.name === options.group) {
        map.controls.add(legend, options.layerId);
      }
    });
    map.on("groupremove", function(e){
      if(e.name === options.group) {
        map.controls.remove(options.layerId);
      }
    });

This adds event listeners so that the legend disappears and reappears with the group.

When you use removeControl() the following JavaScript is run:

methods.removeControl = function(layerId) {
  this.controls.remove(layerId);
};

This removes it from the map, but there are still event listeners that will bring back the legend. Because of this, once you trigger those events (by removing and the adding the group to the map) the legend comes back.