0
votes

I am trying to build a R Shiny Dashboard application with Leaflet library. In the application, a user can select the source country, destination country and product. The dataframe is then filtered for this particular combination of inputs. The resulting dataframe is then passed to renderLeaflet and the location data and details are displayed to the user.

My aim is to only render and display the leaflet plot when the filtered dataframe is created after the user input. I have tried using both validate+need and eventReactive for this. I have added some placeholder data in the leaflet call for now.

eventReactive does not return any leaflet map on the dashboard even after user selects input. eventReactive For validate+need, the leaflet map and placeholder data are plotted and displayed even before user selects input. enter image description here Code for UI.R:


sidebar <- shinydashboard::dashboardSidebar(
  selectizeInput(
    "srcLoc", label="Source Country", choices=locsAgg$SrcLocation, options=list(create=TRUE, maxItems=100, placeholder="Select a Country")
  ),
  selectizeInput(
    "destLoc", label="Destination Country", choices=locsAgg$SonLocation, options=list(create=TRUE, maxItems=100, placeholder="Select a Country")
  ),
  selectizeInput(
    "pdt", label="Product", choices=locsAgg$Pdt, options=list(create=TRUE, maxItems=100, placeholder="Select a Product")
  )
)

body <- shinydashboard::dashboardBody(
  tags$style(type = "text/css", "#map {height: calc(100vh - 80px) !important;}"),
  leafletOutput("map")
)


# Put them together into a dashboardPage
dashboardPage(
  dashboardHeader(title = "World Map"),
  sidebar,
  body
)

Code for Server.R for validate + need:

### Using valid and need --> plot still gets plotted

shinyServer<- function(input,output,session){
  updateSelectizeInput(session, "srcLoc", choices=locsAgg$SrcLocation, server=T)

  locsFil1 <-reactive({
    locsAgg %>% filter(SrcLocation %in% input$srcLoc)
  })

  observeEvent(input$srcLoc, {updateSelectizeInput(session, "destLoc", choices=locsFil1()$SonLocation, server=T)})

  locsFil2 <-reactive({
    locsFil1() %>% filter(SonLocation %in% input$destLoc)
  })

  observeEvent(input$destLoc, {updateSelectizeInput(session, "pdt", choices=locsFil2()$Pdt, server=T)})

  locsFil3 <-reactive({
    locsFil2() %>% filter(Pdt %in% input$pdt)
  })


  output$map <- renderLeaflet({
    validate(
      need(locsFil3(), "Select inputs")
    )
    m <- leaflet(options=leafletOptions(minZoom=1, maxZoom=5, zoomDelta=0.5)) %>% 
      addProviderTiles(providers$OpenStreetMap) %>% setView(lng=-93.85, lat=37.45, zoom=2)
    m <- addMarkers(m, lng=c(12,21) , lat=c(37,67))
  })

}

Code for Server.R for eventReactive:

# doesnt work and messes up filters as well

shinyServer<- function(input,output,session){
  updateSelectizeInput(session, "srcLoc", choices=locsAgg$SrcLocation, server=T)

  locsFil1 <-reactive({
    locsAgg %>% filter(SrcLocation %in% input$srcLoc)
  })

  observeEvent(input$srcLoc, {updateSelectizeInput(session, "destLoc", choices=locsFil1()$SonLocation, server=T)})

  locsFil2 <-reactive({
    locsFil1() %>% filter(SonLocation %in% input$destLoc)
  })

  observeEvent(input$destLoc, {updateSelectizeInput(session, "pdt", choices=locsFil2()$Pdt, server=T)})

  locsFil3 <-reactive({
    locsFil2() %>% filter(Pdt %in% input$pdt)
  })


  output$map <- eventReactive(locsFil3(), {
    renderLeaflet({

      m <- leaflet(options=leafletOptions(minZoom=1, maxZoom=5, zoomDelta=0.5)) %>% 
        addProviderTiles(providers$OpenStreetMap) %>% setView(lng=-93.85, lat=37.45, zoom=2)
      m <- addMarkers(m, lng=c(12,21) , lat=c(37,67))
    })
  }
  )
}

Packages used: defined in Global.R:

packages = c("shiny",
             "shinydashboard",
             "dplyr",
             "openxlsx",
             "stringr",
             "readr",
             "tidyr",
             "leaflet",
             "geosphere")

How do I update the server.R code for the leaflet plot to render only once the filtered dataframe becomes available? Thank you!

1
Your leaflet does not depend on any reactive value (in particular, it does not depend on locsFil3()). Is it normal?Stéphane Laurent
@StéphaneLaurent it does depend on locsFil3() in my actual code. But i just added some placeholder values for now for the purpose of posting on Stack Overflow. Thanks!Daxaniie

1 Answers

1
votes

It's hard to help without having the dataset locsAgg.

I would try

locsFil3 <- eventReactive(list(locsFil2(), input$pdt), {
  locsFil2() %>% filter(Pdt %in% input$pdt)
}, ignoreInit = TRUE)

output$map <- renderLeaflet({
  req(locsFil3())
  m <- leaflet(options=leafletOptions(minZoom=1, maxZoom=5, zoomDelta=0.5)) %>% 
    addProviderTiles(providers$OpenStreetMap) %>% setView(lng=-93.85, lat=37.45, zoom=2)
  addMarkers(m, lng=c(12,21) , lat=c(37,67))
})

or

locsFil3 <- reactive({
  locsFil2() %>% filter(Pdt %in% input$pdt)
})

 observeEvent(locsFil3(), {
   output$map <- renderLeaflet({
    m <- leaflet(options=leafletOptions(minZoom=1, maxZoom=5, zoomDelta=0.5)) %>% 
      addProviderTiles(providers$OpenStreetMap) %>% setView(lng=-93.85, lat=37.45, zoom=2)
    addMarkers(m, lng=c(12,21) , lat=c(37,67))
  })
}, ignoreInit = TRUE)

If that does not work, please provide locAggs (edit your question and paste the output of dput(locsAgg), or dput(head(locsAgg,20)) if this is enough).