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. For validate+need, the leaflet map and placeholder data are plotted and displayed even before user selects input. 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!
locsFil3()
). Is it normal? – Stéphane Laurent