I have a shiny app with an existing leaflet map in it. I want to be able to manipulate this map after rendering, using custom javascript through the shinyjs
package. A minimal example is below:
app.R
# packages ----------------------------------------------------------------
library(dplyr)
library(leaflet)
library(shiny)
library(shinyjs)
# ui ----------------------------------------------------------------------
ui <- fluidPage(
useShinyjs(),
extendShinyjs(script = "my_js.js"),
leafletOutput(outputId = "map", height = "80vh"),
tags$hr(),
tags$p("Button to run the JS code"),
actionButton(inputId = "go", label = "Add a Marker")
)
# server ------------------------------------------------------------------
server <- function(input, output, session){
# define a simple map
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron")
})
# observe the go button and run the shinyjs.addMarker function
observeEvent(
eventExpr = input$go,
handlerExpr = js$addMarker()
)
}
# run ---------------------------------------------------------------------
shinyApp(ui = ui, server = server)
my_js.js
shinyjs.addMarker = function(){
// get the map - this bit doesn't work!
var map = document.getElementById('map');
// create a marker and add to map
var marker = new L.marker([53, -1]).addTo(map);
// really I'd be going off and querying an API, or doing
// something else for which there is no handy R function.
};
The question really is how to access the map object after it has been created. Obviously with this example I'm just adding a marker, which I could do with leafletProxy()
, but in reality I want to query an API and bring extra data onto the map when the user performs an action.
You can reach the map object with htmlwidtget
's onRender()
function. Then, you might save it to the globally scoped variable (by skipping the var
keyword while creating the variable). This becomes available anywhere in the JavaScript code.
output$map <- renderLeaflet({
leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
htmlwidgets::onRender("
function(el,x) {
map = this;
}
")
})
Your my_js.js would then look as follows:
shinyjs.addMarker = function(){
// create a marker and add to map
var marker = new L.marker([53, -1]).addTo(map);
// really I'd be going off and querying an API, or doing
// something else for which there is no handy R function.
};