Search code examples
rshinyflexdashboardr-leaflet

Shiny Leaflet map with conditional logic doesn't render initial map markers


I'm building a Leaflet map using Shiny and Flexdashboard. The map is hidden behind introduction text using conditional panels. It loads for the first time after the user makes a selection from an input.

The initial output$map should only load once (due to large polygon layers that do not need to be reloaded), but the map markers should update whenever the user inputs change.

The first time the map loads, it does not load the markers. If the inputs change after the map loads, the markers load properly. My goal is to get the map markers to load after the first selection.

I don't include addCircleMarkers in output$map because I don't want the full map -- polygons and all -- to load every time the user inputs / reactive variable changes.

After extensive digging, I found this suggestion, but I'm struggling to relate the answer to my code. Maybe I'm too close to the code to see the answer. I appreciate any help.

Here is a stripped down example:

```{r setup, include=FALSE}

library(leaflet)
library(shiny)
library(shinyjs)
library(flexdashboard)
library(dplyr)

chargeslist <- c("Charge One","Charge Two")

chargesdf <- data.frame(chargeslist)

userselects <- reactive({
  if(input$charges != "") {
    charges <- chargesdf[chargesdf$chargeslist %in% input$charges, ]
  } else {
    return(NULL)
  }
})

output$intro <- renderUI({
  HTML("Introduction text")
})

output$map = renderLeaflet({
  leaflet('map') %>% addTiles() %>%
  addProviderTiles('CartoDB.Positron') %>%
  setView(-95.37, 29.75, zoom = 10)
})

outputOptions(output, 'intro', suspendWhenHidden=FALSE)

outputOptions(output, 'map', suspendWhenHidden=TRUE) # unless suspendWhenHidden set to TRUE, it doesn't render markers through the observer

output$stats <- reactive({ !is.null(userselects()) }) # universal controller for conditional panels

observe({
req(input$charges)
leafletProxy("map", data = userselects()) %>%
  clearMarkerClusters() %>%
  addCircleMarkers(lng = ~ Longitude, lat = ~ Latitude, color = "#b20000", radius = 10), clusterOptions = markerClusterOptions())
})

```

Sidebar {.sidebar}
=====================================

```{r}

selectizeInput("charges", "Charges", c("Choose one   " = "", as.character(chargeslist)))

```

Map
=====================================  

Row
-----------------------------------------------------------------------
```{r}

div(style="width:100%; float:left;",
  conditionalPanel(condition = '!output.stats', 
                   uiOutput('intro') 
))

div(style="width:100%;", 
 conditionalPanel(condition = 'output.stats', 
  div(id="",
      class="",
      leafletOutput('map') 
)))

```

Solution

  • Instead of using observers, I defined the map markers as an output:

    output$markers <- renderPlot({
      leafletProxy("map", data = userselects()) %>%
          clearMarkerClusters() %>%
          addCircleMarkers(lng = ~ Longitude, lat = ~ Latitude, 
                           color = "#b20000", radius = 10)
    })
    

    Then called the output right after leaflet:

    div(style="width:100%;",
      conditionalPanel(condition = 'output.stats', 
        div(id="",
        class="",
        leafletOutput('map'),
        plotOutput('markers')
      )))
    

    Seems like an imperfect solution, but it will work for now.