R Shiny leaflet: using observers
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Using leaflet in R is fairly simple and there are plenty of online resources and examples available already. See the RStudio tutorial to get started if you haven’t already. This post presents a series of examples which build upon each other.
The code displays both point data and raster data on leaflet maps with Shiny app integration. The focus here is to show the utility of event observation on the server side for integrating the behavior of browser elements, namely, the leaflet map.
In the course of these examples, I’ll also use a modal from the shinyBS package and the maps will be full size in the browser window with UI widgets laid on top using absolute panels. The full post contains interactive embedded Shiny widgets. See the full post here. It includes complete source code for these and other related apps using leaflet.
The app does not do much in this version, but it provides a clear view of how to use observers in Shiny apps to ensure that various inputs and outputs remain mutually well behaved. Here I use observeEvent
three distinct times to tie together the reactive behavior of instances of selectInput
and leafletOutput
. The entire ui.R
at this point is:
ui <- bootstrapPage( tags$style(type="text/css", "html, body {width:100%;height:100%}"), leafletOutput("Map", width="450", height="100%"), absolutePanel(top=10, right=10, selectInput("location", "Community", c("", locs$loc), selected=""), conditionalPanel("input.location !== null && input.location !== ''", actionButton("button_plot_and_table", "View Plot/Table", class="btn-block")) ) )
In server.R
note the three observers. They constitute the entire code block except for the initial, relatively simple call to renderLeaflet
. Comments mark the role performed by each call to observeEvent
, which:
- Update the leafletOutput map when clicked
- Update the selectInput when the map is clicked
- Update the leafletOutput when the selectInput changes
server <- function(input, output, session) { acm_defaults <- function(map, x, y) addCircleMarkers(map, x, y, radius=6, color="black", fillColor="orange", fillOpacity=1, opacity=1, weight=2, stroke=TRUE, layerId="Selected") output$Map <- renderLeaflet({ leaflet() %>% setView(lon, lat, 4) %>% addTiles() %>% addCircleMarkers(data=locs, radius=6, color="black", stroke=FALSE, fillOpacity=0.5, group="locations", layerId = ~loc) }) observeEvent(input$Map_marker_click, { # update the map markers and view on map clicks p <- input$Map_marker_click proxy <- leafletProxy("Map") if(p$id=="Selected"){ proxy %>% removeMarker(layerId="Selected") } else { proxy %>% setView(lng=p$lng, lat=p$lat, input$Map_zoom) %>% acm_defaults(p$lng, p$lat) } }) observeEvent(input$Map_marker_click, { # update the location selectInput on map clicks p <- input$Map_marker_click if(!is.null(p$id)){ if(is.null(input$location) || input$location!=p$id) updateSelectInput(session, "location", selected=p$id) } }) observeEvent(input$location, { # update the map markers and view on location selectInput changes p <- input$Map_marker_click p2 <- subset(locs, loc==input$location) proxy <- leafletProxy("Map") if(nrow(p2)==0){ proxy %>% removeMarker(layerId="Selected") } else if(length(p$id) && input$location!=p$id){ proxy %>% setView(lng=p2$lon, lat=p2$lat, input$Map_zoom) %>% acm_defaults(p2$lon, p2$lat) } else if(!length(p$id)){ proxy %>% setView(lng=p2$lon, lat=p2$lat, input$Map_zoom) %>% acm_defaults(p2$lon, p2$lat) } }) } shinyApp(ui, server)
Care must be taken to ensure each observer does not update when it shouldn’t. One can easily trigger another back and forth in this context. Fortunately it is not too difficult to make the three observeEvent
calls work well together. See the full post to use the app and continue with the interactive examples.
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.