Search code examples
rshinyr-leaflet

render leaflet markers across tabs on shiny startup


I'm trying to create two leaflet maps in an R shiny app that are placed in different tabpanels using the tabsetPanel() function. I would like to have a widget (e.g., sliderInput()) that controls the size of markers on both maps. I can create an app that does this but the problem is that features are not initially rendered on the map that is on the second panel on startup. Features are rendered on the second panel only after selecting the panel, then changing the input with a slider. I would like both maps to show their features on startup without having to initialize the second with a slider.

library(shiny)
library(leaflet)

pts <- data.frame(
  x = rnorm(10, mean = -93.625), 
  y = rnorm(10, mean = 42.0285)
)


# Define UI 
ui <- fluidPage(

   sliderInput("radius",
           "Point radius:",
           min = 1,
           max = 50,
           value = 30),

    tabsetPanel(

      tabPanel('Map1',

      leafletOutput('map1')   

      ), 

      tabPanel('Map2', 

       leafletOutput('map2')   

      )
   )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

  output$map1 <- renderLeaflet({
    leaflet() %>% 
      addTiles() %>% 
      setView(-93.65, 42.0285, zoom = 6)
    })
  output$map2 <- renderLeaflet({
    leaflet() %>% 
      addTiles() %>% 
      setView(-93.65, 42.0285, zoom = 6)
  })

  observe({

    tab1 <- leafletProxy('map1', data = pts) %>%
      clearMarkers() %>% 
      addCircleMarkers(lng = ~x, lat = ~y, radius = input$radius)

    tab2 <- leafletProxy('map2', data = pts) %>% 
      clearMarkers() %>% 
      addCircleMarkers(lng = ~x, lat = ~y, radius = input$radius)

  })

}

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

Solution

  • As a simple fix, you could give your tabsetPanel an id, and put the corresponding input in your observer, so that the observer also invalidates when you change tabs. Working example is given below, I hope this helps!


    enter image description here

    library(shiny)
    library(leaflet)
    
    pts <- data.frame(
      x = rnorm(10, mean = -93.625), 
      y = rnorm(10, mean = 42.0285)
    )
    
    
    # Define UI 
    ui <- fluidPage(
      sliderInput("radius",
                  "Point radius:",
                  min = 1,
                  max = 50,
                  value = 30),
      tabsetPanel(id='my_tabsetPanel',
        tabPanel('Map1',
                 leafletOutput('map1')   
        ), 
        tabPanel('Map2', 
                 leafletOutput('map2')   
        )
      )
    )
    
    # Define server logic required to draw a histogram
    server <- function(input, output) {
    
      output$map1 <- renderLeaflet({
        leaflet() %>% 
          addTiles() %>% 
          setView(-93.65, 42.0285, zoom = 6)
      })
      output$map2 <- renderLeaflet({
        leaflet() %>% 
          addTiles() %>% 
          setView(-93.65, 42.0285, zoom = 6)
      })
    
      observe({
    
        input$my_tabsetPanel
    
        tab1 <- leafletProxy('map1', data = pts) %>%
          clearMarkers() %>% 
          addCircleMarkers(lng = ~x, lat = ~y, radius = input$radius)
    
        tab2 <- leafletProxy('map2', data = pts) %>% 
          clearMarkers() %>% 
          addCircleMarkers(lng = ~x, lat = ~y, radius = input$radius)
    
      })
    
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)