How to save each click that the user gives on the map and access them individually? Shiny Leaflet R

Viewed 132
library(shiny)
library(leaflet)
library(leaflet.providers)
ui <- fluidPage(
  leafletOutput('map',width = "1331",height = "400"))
  
server <- function(input, output, session){
  output$map <- renderLeaflet({
    m<-leaflet() %>%
      addProviderTiles(providers$OpenStreetMap,
                       options = providerTileOptions(noWrap = TRUE))%>%
      setView(lng =-73.935242, lat =40.730610, zoom= 12)})
  
  
  observe({  click = input$map_click
  if(is.null(click))
    return()
  else
    clicks=data.frame(click[1:2])
  leafletProxy("map") %>%
    addMarkers(data = clicks) #Adds a marker on each click

    
  clicklist <<- reactiveVal(list()) # empty list
  observeEvent(input$map_click, {
    click <- input$map_click
    temp <<- clicklist() # get the list of past clicks 
    temp[[length(temp)+1]] <<- click[1:2] # add this click to the list
    clicklist(temp)
    print(clicklist)})  #show on the console  lat and lng

  })
    }
shinyApp(ui = ui, server = server)

enter image description here an image to attract your attention

Console:

reactiveVal: [1] "40.74778, -73.97953" 
reactiveVal: [1] "40.73191, -73.99704" 
reactiveVal: [1] "40.73191, -73.99704" "40.73191, -73.99704" 

The code above saves only the last user click on the map in the "clicklist" object, and repeats it as many times as the user clicks on the map.

>clicklist
reactiveVal: [1] "40.72931, -73.99326" "40.72931, -73.99326" "40.72931, -73.99326" 

The object class is reactivevalue.

> class(clicklist)
[1] "reactiveVal" "reactive"

How to save each click and access them individually?

Expected output

>clicklist
[[1]]
[1]40.74778 -73.97953
[[2]]
[1]40.73191 -73.99704 

>clicklist[1]
[1] 40.74778, -73.97953

>clicklist[1][[1]][1]
[1] 40.74778

>clicklist[1][[1]][2]
-73.97953

>clicklist[2]
[[1]]
[1]  40.73191 -73.99704

>clicklist[2][[1]][1]
[1] 40.73191

> clicklist[2][[1]][2]
[1] -73.99704
1 Answers

The following code gives the expected output, your expected output is a list of vectors but input$map_click gives a list, a named list to be exact. To convert it to a vector, we used unlist, since your desired output doesn't have names in the vector as well, we used unname to remove the names. Also, if your code is breaking on app initialization due to the unavailability of some input, use req to have observers wait for that input. This is one of the recommended approaches to handle this kind of behavior. << is not recommended in shiny apps and is to be used very carefully. In your code, it was actually redundant.

library(shiny)
library(leaflet)
library(leaflet.providers)
ui <- fluidPage(
  leafletOutput('map',width = "1331",height = "400"))

server <- function(input, output, session){
  output$map <- renderLeaflet({
    m <-leaflet() %>%
      addProviderTiles(providers$OpenStreetMap,
                       options = providerTileOptions(noWrap = TRUE))%>%
      setView(lng =-73.935242, lat =40.730610, zoom= 12)})


  observe({
    req(input$map_click)
    clicks <- data.frame(input$map_click[1:2])
    leafletProxy("map") %>%
      addMarkers(data = clicks) #Adds a marker on each click
  })

  clicklist <- reactiveVal(list()) # empty list

  observeEvent(input$map_click, {
    click <- input$map_click
    temp <- clicklist() # get the list of past clicks 
    temp[[length(temp)+1]] <- unname(unlist(click[1:2])) # add this click to the list
    clicklist(temp)
    print(clicklist())
  })  #show on the console  lat and lng
}

shinyApp(ui = ui, server = server)
Related