Search code examples
rshinyr-leaflet

Shiny Leaflet Hiding a conditional panel with a mouse click event


I would like to create a plot in the absolutePanel, using a conditionalPanel, that only appears when i click the mouse on the basemap. This is no problem and i've achieved that.

But i'd like the plot to clear and the conditionalPanel to collapse again once the user crosses off the point pop-up. At the moment the plot changes and replots data when another click is performed but it is the clearing of the pop-up that I would like linked to the collapsing of the conditionalPanel;

This very simple example shows the creation of the conditionalPanel upon click (the full version creates a point and reads a raster stack to plot a timeline):

ui <- bootstrapPage(
  tags$style(type = "text/css", "html, body {width:100%;height:100%}"),
  leafletOutput("map", width="100%", height="100%"),
  absolutePanel(class = "panel panel-default", fixed = TRUE,draggable = TRUE,
                top = 20, left = 60,
                
                conditionalPanel("input.map_click",
                   h4(textOutput("Click_text")),
                top=20, left=60, height=400, width=200,
                style="padding-left: 10px; padding-right: 8px; padding-top: 8px; padding-bottom: 8px")
  )
)


server <- function(input, output, session) {
  
  output$map <- renderLeaflet({
    leaflet() %>%
      setView(-4,52.5,9) %>%
      addProviderTiles(providers$CartoDB.Positron)  
  })
  
  observeEvent(input$map_click, {
    click <- input$map_click
    text<-paste("Lattitude ", click$lat, "Longtitude ", click$lng)
    text2 <- paste("YOUVE CLICKED THE MAP!!!",click$lat, click$lng)
    
    proxy <- leafletProxy("map")
    proxy %>% clearPopups() %>%
      addPopups(click$lng, click$lat, text)
    
    output$Click_text<-renderText({text2})
  })
  
}

runApp(shinyApp(ui, server), launch.browser = TRUE)

There is a suggestion in the documentation that there is an event called mouseout but it might just be linked to clicks on actual markers, as opposed to the maptile clicks, as I certainly couldn't get it to work. Is there any way to make the panel disappear after crossing off the pop-up?


Solution

  • It seems indeed that the popup_close event is still not implemented in leaflet for R.

    Nonetheless we can build it using the awesome htmlwidgets package.

    library(htmlwidgets)
    

    We will use some javascript to:

    • listen to the popupclose & popupopen events.
    • send the information that the events happened to Shiny.

    This can all be accomplished inside the onRender() function:

    output$map <- renderLeaflet({
            leaflet() %>%
                setView(-4,52.5,9) %>%
                addProviderTiles(providers$CartoDB.Positron) %>% 
    
                onRender("
                         function(el, x) {
                             this.on('popupopen', function(e) {
                                 Shiny.onInputChange('myEvent', 'open');
                             });
    
                             this.on('popupclose', function(e) {
                                 Shiny.onInputChange('myEvent', 'close');
                             });
                         }")
        })
    

    onRender() adds some javascript code to be executed once the map is rendered.
    In this case this.on('popupopen', function()) create the event listener, while Shiny.onInputChange('myEvent', 'close') assigns the value close to input$myEvent.

    We now only need to change the condition for the panel:

     conditionalPanel("input.myEvent == 'open'", ...)