Search code examples
rshinyr-leaflet

How to create a modal window on clicking an icon?


I want to create a modal window when I click an icon in a leaflet map in shiny. Is this doable? I tried the code below, but the bsModal is not doing anything.

library(shiny)
library(leaflet)
library(shinyBS)

points <- data.frame(cbind(latitude = rnorm(40) * 2 + 13, longitude  = 
rnorm(40) + 48))


ui <- fluidPage(
  leafletOutput("mymap"),
    bsModal("modalExample", "This will open a modal", "assign_task", size = 
      "large",
    HTML(""))
    )

   server <- function(input, output, session) {



   output$mymap <- renderLeaflet({
   leaflet(options = leafletOptions(maxZoom = 18)) %>% addTiles() %>%
    addMarkers(lat = ~ latitude, lng = ~ longitude,
             data = points,
             popup=~ sprintf(
               '<button type="button" id="assign_task">Open Modal </button>'
             ))
   })
  }

shinyApp(ui, server)

enter image description here


Solution

  • I'll post two possible solutions. The first one is the solution that I think would suit your needs best, the second one more cosely matches your current code. Hope this helps!


    Solution 1:

    library(shiny)
    library(leaflet)
    
    points <- data.frame(cbind(id=seq(1,40),latitude = rnorm(40) * 2 + 13, longitude  = 
                                 rnorm(40) + 48))
    
    
    ui <- fluidPage(
      leafletOutput("mymap"),
      actionButton("action1","Show modal")
    )
    
    server <- function(input, output, session) {
    
      observeEvent(input$mymap_marker_click, {
        id = input$mymap_marker_click$id
        showModal(modalDialog(
          title = "You selected a marker!",
          paste0("ID: ", id, ", lat: ", round(points$latitude[id==id],2),", lon: ", round(points$longitude[id==id],2))
        ))
      })
    
      output$mymap <- renderLeaflet({
        leaflet(options = leafletOptions(maxZoom = 18)) %>% addTiles() %>%
          addMarkers(layerId =  ~ id,lat = ~ latitude, lng = ~ longitude,
                     data = points
          )
      })
    }
    
    shinyApp(ui, server)
    

    Solution 2:

    library(shiny)
    library(leaflet)
    library(shinyBS)
    
    points <- data.frame(cbind(latitude = rnorm(40) * 2 + 13, longitude  = 
                                 rnorm(40) + 48))
    
    
    ui <- fluidPage(
      leafletOutput("mymap"),
        actionButton("action1","Show modal")
    )
    
    server <- function(input, output, session) {
    
      observeEvent(input$button_click, {
        showModal(modalDialog(
          title = "Important message",
          "This is an important message!"
        ))
      })
    
      output$mymap <- renderLeaflet({
        leaflet(options = leafletOptions(maxZoom = 18)) %>% addTiles() %>%
          addMarkers(lat = ~ latitude, lng = ~ longitude,
                     data = points,
                     popup= ~paste("<b>", latitude, longitude, "</b></br>", actionButton("showmodal", "Show modal", onclick = 'Shiny.onInputChange(\"button_click\",  Math.random())')))
      })
    }
    
    shinyApp(ui, server)