Search code examples
rshinyr-leaflet

Clear leaflet markers in shiny app with slider bar


I'm trying to build a shiny app that will only plot points on rows that have a value within the range of a slider bar. If I increase the range of the slider bar, points will be added, but points are never removed when I decrease the range of the slider bar. Below is a reproducible example of my problem.If you increase the slider bar to full range, 3 points will show up on the map. If you then decrease the range enough it will zoom in on one point, but if you zoom out you will see that there are still 3 points being plotted on a map. I thought the clearShapes or clearMarkers function in leaflet would remove these points, but it's not working. Do you have any suggestions?

library(shiny)
library(leaflet)
library(tidyverse)

ui <- fluidPage(
   
   titlePanel("Test"),
  
   sidebarLayout(
      sidebarPanel(
         radioButtons("choice","Group:",choices = c(1,2), selected = 1),
         uiOutput("value"),
         verbatimTextOutput("Click_text")
      ),
      
      mainPanel(
         leafletOutput("Map")
      )
   )
)

server <- function(input, output) {
  
  df <- data.frame(lat = c(42.34,43.65,45.26,48.63,47.65,47.52),
                   lng = c(-96.43,-97.45,-98.56,-92.35,-94.56,-95.62),
                   id = c(32,45,65,76,34,12),
                   grp = c(1,1,1,2,2,2),
                   val = c(1.75,2.12,3.2,3.32,4.76,4.85))
  
  subsetData1 <- reactive({

    df %>% filter(grp == input$choice)

  })

  output$value <- renderUI({
    
    sliderInput("value",label = h3("value"),
                min = min(subsetData1()$val,na.rm = TRUE),
                max = max(subsetData1()$val,na.rm=TRUE),
                value = c(quantile(subsetData1()$val,.25,na.rm = TRUE),quantile(subsetData1()$val,.75,na.rm=TRUE))) 
    
  })      
  
  subsetData <- reactive({
    
    df2 <- subsetData1() %>% data.frame()
    
    df2 %>% filter(val >= min(as.numeric(input$value)) & val <= max(as.numeric(input$value)))
    
  })   
  
  output$Map <- renderLeaflet({
    
    leaflet(height = 1000) %>% 
      addTiles() %>% 
      fitBounds(min(df$lng),min(df$lat),max(df$lng),max(df$lat))
    
  })
  
  observe({
    leafletProxy("Map") %>%
      clearMarkers() %>%
      clearShapes() %>%
      addCircleMarkers(data = subsetData(),
                       lng  = ~lng,
                       lat  = ~lat,
                       layerId = ~id,
                       radius = 8,
                       weight = 10) %>%
      fitBounds(.,min(subsetData()$lng),min(subsetData()$lat),
                max(subsetData()$lng),max(subsetData()$lat))
    
  })
  
  observe({

    click<-input$Map_marker_click
    if(is.null(click))
      return()
    text<-paste("Latitude ", click$lat, "Longtitude ", click$lng)
    text2<-paste("You've selected point ", click$id)

    output$Click_text<-renderText({
      text2
    })

  })

}

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

Solution

  • You can change your observe function where you clear markers to an observeEvent function.

      observeEvent(input$value,{
        leafletProxy("Map") %>%
          clearMarkers() %>%
          clearShapes() %>%
          addCircleMarkers(data = subsetData(),
                           lng  = ~lng,
                           lat  = ~lat,
                           layerId = ~id,
                           radius = 8,
                           weight = 10) %>%
          fitBounds(.,min(subsetData()$lng),min(subsetData()$lat),
                    max(subsetData()$lng),max(subsetData()$lat))
    
      })
    

    You also have both the uiOutput and sliderInput id's as the same (value). You should make sure every element has a unique id. Rename one of them to something unique.