Search code examples
rshinyr-leaflet

Leaflet output in two tabs : LeafletProxy() doesn't render initially in 2nd tab


I have two leaflet output with two leafletproxy, each rendering on two different tabpanel inside a tabsetpanel. the problem is that the second leafletproxy doesn't render when I select the second panel, I need to select an input first. My goal is to render the second leaflet proxy when I select the second tab without select an input first.

I have found some solution on the internet but these doesn't suit me:

in the line 83 is this solution: render leaflet markers across tabs on shiny startup

in the line 84 is this solution: https://github.com/rstudio/leaflet/issues/590

the problem with theses solutions is that when you come back and forth to the second panel, the leaflet proxy re-load (see the console). It is not a problem when you have a little amount of data, but that is not my case...

So i would like to render the leafletproxy of the second tab only once, when the shinyApp starts. How can I do that?

library(shiny)
library(leaflet)
library(RColorBrewer)


ui <- fluidPage(
  
  tags$style(HTML("
                  #map1 {
                  position: absolute;
                  }
                  #map2 {
                  position: absolute;
                  }
                  ")),
  
  conditionalPanel(
    condition = "input.tabs=='tabMap1'",
    leafletOutput("map1", width="100%", height = "100%")
    ),
  
  conditionalPanel(
    condition = "input.tabs=='tabMap2'",
    leafletOutput("map2", width="100%", height = "100%")
  ),
  
  absolutePanel(
    id = "tabPanel",
    class = "panel panel-default",
    style = "padding : 10px",
    top = "2%", 
    left = "2%",
    right = "78%",
    height= "50%",
    tabsetPanel(id = "tabs", 
      tabPanel("tabMap1",
               selectInput("colors1", "Color Scheme",
                           rownames(subset(brewer.pal.info, category %in% c("seq", "div")))
               )),
      tabPanel("tabMap2",
               selectInput("colors2", "Color Scheme",
                           rownames(subset(brewer.pal.info, category %in% c("seq", "div")))
               )
      )
    )
  )
)

server <- function(input, output, session) {
  
  # Leaflet Output Map 1
  output$map1 <- renderLeaflet({
    leaflet(quakes) %>% addTiles() %>%
      fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))
  })
  
  colorpal1 <- reactive({
    colorNumeric(input$colors1, quakes$mag)
  })
  
  # leaflet Proxy Map 1
  observe({
    pal1 <- colorpal1()
    leafletProxy("map1", data = quakes) %>%
      clearShapes() %>%
      addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                 fillColor = ~pal1(mag), fillOpacity = 0.7, popup = ~paste(mag)
      )
  })
  
  # Leaflet Output Map 2
  output$map2 <- renderLeaflet({
    leaflet(quakes) %>% addTiles() %>%
      fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))
  })
  
  colorpal2 <- reactive({
    colorNumeric(input$colors2, quakes$mag)
  })
  
  # leaflet Proxy Map 2
  observe({
    # input$tabs
    # req(input$tabs == "tabMap2")
    pal2 <- colorpal2()
    leafletProxy("map2", data = quakes) %>%
      clearShapes() %>%
      addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                 fillColor = ~pal2(mag), fillOpacity = 0.7, popup = ~paste(mag)
      )
  })
}

shinyApp(ui, server)

Solution

  • I managed to find a solution by adding an isolate() on my reactive data and the layer (addCircles) of the leaflet proxy inside the renderLeaflet, it goes like this :

    library(shiny)
    library(leaflet)
    library(RColorBrewer)
    
    
    ui <- fluidPage(
    
      tags$style(HTML("
                      #map1 {
                      position: absolute;
                      }
                      #map2 {
                      position: absolute;
                      }
                      ")),
    
      conditionalPanel(
        condition = "input.tabs=='tabMap1'",
        leafletOutput("map1", width="100%", height = "100%")
      ),
    
      conditionalPanel(
        condition = "input.tabs=='tabMap2'",
        leafletOutput("map2", width="100%", height = "100%")
      ),
    
      absolutePanel(
        id = "tabPanel",
        class = "panel panel-default",
        style = "padding : 10px",
        top = "2%", 
        left = "2%",
        right = "78%",
        height= "50%",
        tabsetPanel(id = "tabs", 
                    tabPanel("tabMap1",
                             selectInput("colors1", "Color Scheme",
                                         rownames(subset(brewer.pal.info, category %in% c("seq", "div")))
                             )),
                    tabPanel("tabMap2",
                             selectInput("colors2", "Color Scheme",
                                         rownames(subset(brewer.pal.info, category %in% c("seq", "div")))
                             )
                    )
        )
      )
      )
    
    server <- function(input, output, session) {
    
      # Leaflet Output Map 1
      output$map1 <- renderLeaflet({
        print("map1")
        leaflet(quakes) %>% addTiles() %>%
          fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))
      })
    
      colorpal1 <- reactive({
        colorNumeric(input$colors1, quakes$mag)
      })
    
      # leaflet Proxy Map 1
      observe({
        print("map1")
        pal1 <- colorpal1()
        leafletProxy("map1", data = quakes) %>%
          clearShapes() %>%
          addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                     fillColor = ~pal1(mag), fillOpacity = 0.7, popup = ~paste(mag)
          )
      })
    
      # Leaflet Output Map 2
      output$map2 <- renderLeaflet({
    
        foo <- leaflet(quakes) %>% addTiles() %>%
          fitBounds(~min(long), ~min(lat), ~max(long), ~max(lat))
    
        pal2 <- isolate(colorpal2())
        foo %>% addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                           fillColor = ~pal2(mag), fillOpacity = 0.7, popup = ~paste(mag))
      })
    
      colorpal2 <- reactive({
        colorNumeric(input$colors2, quakes$mag)
      })
    
      # leaflet Proxy Map 2
      observe({
        # input$tabs
        #req(input$tabs == "tabMap2")
        pal2 <- colorpal2()
        leafletProxy("map2", data = quakes) %>%
          clearShapes() %>%
          addCircles(radius = ~10^mag/10, weight = 1, color = "#777777",
                     fillColor = ~pal2(mag), fillOpacity = 0.7, popup = ~paste(mag)
          )
      })
    }
    
    shinyApp(ui, server)