I am making an application using shiny that uses multiple tabs. On one tab (not the starting tab) I display a leaflet map, which is controlled by widgets on different tabs.
The issue is that if I change the inputs on one tab, without visiting the map first, and then visit the map, the map is not updated. However, changing the inputs after or while being on the map tab, the map is updated.
To replicate the issue:
- run the following code
- change the input color to blue (without visiting the map tab first!)
- go to the "Map" tab
- expected behavior: blue dot. Actual behavior: no dot (not yet drawn, as if the
observe()
didn't get triggered (note that observe is triggered but has no effect), or the leaflet was not rendered)
- expected behavior: blue dot. Actual behavior: no dot (not yet drawn, as if the
- change the color to yellow
- yellow dot appears
- go to the "Other" tab and change color to green
- go back to the "Map" tab and see a green dot
Similarly, when the app is started and we directly go to the map, I would expect a red dot to be displayed. Instead there is no dot.
Code:
library(shiny)
library(leaflet)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("color", "Color", choices = c("red", "blue", "yellow", "green"))
),
mainPanel(
tabsetPanel(
tabPanel("Other", h1("Empty Tab 1")),
tabPanel("Map", leafletOutput("map"))
)
)
)
)
server <- function(input, output, session) {
# the base map and the circles are separated due to data restrictions
# in the actual app!
output$map <- renderLeaflet({
leaflet() %>%
addTiles()
})
observe({
leafletProxy("map") %>%
addCircles(lng = 0, lat = 0, radius = 3e6, color = input$color)
})
}
shinyApp(ui, server)
I suspect that leafletProxy
doesn't work as the leaflet widget is not yet rendered in step 2.
Any idea how to fix this issue?
In my real-life app, the first tab allows the user to upload data, while the second tab displays the data using leaflet, therefore the leaflet map gets updated and configured before its actually rendered...
Note that creating the leaflet in one go (Creating the map in the observe()
without leafletProxy
) is not an option due to various reason (size of leaflet, being dependent on other reactive values, scenarios etc.).