Search code examples
javascriptrshinygeolocation

Vectors of latitude and longitude in geolocation app in shiny


I am building and app, that includes geolocation captures using the geoloc package

This is an example app:

library(shiny)
library(leaflet)
library(geoloc)

ui <- fluidPage(
  h2("Where Am I?"),
  tags$p("Click the button to get your location"),
  geoloc::button_geoloc("myBtn", "Get my Location"),
  tags$br(),
  textOutput("coords"),
  textOutput("col"),
  leafletOutput("lf")
)

server <- function(input, output) {
  output$coords <- renderText(paste(input$myBtn_lat, input$myBtn_lon, sep = ", "))
  
  Lats <- reactiveValues(Lat = NULL)
  
  observeEvent(input$myBtn_lat, {
    Lats$Lat <- append(Lats$Lat, input$myBtn_lat)
  })
  
  
  output$col <- renderText({
    Lats$Lat
  })
  
  output$lf <- renderLeaflet({
    req(input$myBtn_lon)
    req(input$myBtn_lat)
    leaflet() %>%
      addTiles() %>%
      setView(as.numeric(input$myBtn_lon), as.numeric(input$myBtn_lat), zoom = 17) %>%
      addMarkers(as.numeric(input$myBtn_lon), as.numeric(input$myBtn_lat), label = "You're here!")
  })
}

shinyApp(ui, server)

I have two questions for this:

How to get a vector of latitudes and longitudes with the button

I need this because usually, we like to take 4 or 5 times the location and then use the median.

This has been addressed in this question, however, there are some kinks I can't figure out since the button is a custom one, and the inputs are not input$myBtn, but input$myBtn_lat and input$myBtn_lon, I find it hard to compute. This is what I am trying to do with the observe events

How to transform this into shiny modules

This will go to a larger shiny app, so I would love to generate modules for this, but again, the facto that the input in ui is "myBtn", but then in the server I have 2 inputs (MyBtn_lon and MyBtn_lat), make it very hard to figure out

Any help is welcome


Solution

  • How about the following code with Shiny modules? I tested and it worked.

    library(shiny)
    library(leaflet)
    library(geoloc)
    
    mapUI <- function(id, label = "Location in map"){
      ns <- NS(id)
      
      tagList(
        geoloc::button_geoloc(ns("myBtn"), "Get my Location"),
        tags$br(),
        textOutput(ns("coords")),
        textOutput(ns("col")),
        textOutput(ns("md")), # for median latitude
        leafletOutput(ns("lf"))
      )
    }
    
    mapServer <- function(id){
      moduleServer(
        id,
        function(input, output, session){
          output$coords <- renderText(paste(input$myBtn_lat, input$myBtn_lon, sep = ", "))
          
          Lats <- reactiveValues(Lat = NULL)
          
          observeEvent(input$myBtn, {
            Lats$Lat <- c(Lats$Lat, input$myBtn_lat)
          })
          
          
          output$col <- renderText({
            Lats$Lat 
          })
          
          # add median latitude
          output$md <- renderText({
            req(input$myBtn_lat)
            if(length(Lats$Lat) %% 5 == 0){
              paste0("Median latitute is: ", median(Lats$Lat))
            } 
          })
          
          output$lf <- renderLeaflet({
            req(input$myBtn_lon)
            req(input$myBtn_lat)
            leaflet() %>%
              addTiles() %>%
              setView(as.numeric(input$myBtn_lon), as.numeric(input$myBtn_lat), zoom = 17) %>%
              addMarkers(as.numeric(input$myBtn_lon), as.numeric(input$myBtn_lat), label = "You're here!")
          })
        }
      )
    }
    
    ui <- fluidPage(
      h2("Where Am I?"),
      tags$p("Click the button to get your location"),
      mapUI("map1")
    )
    
    server <- function(input, output, session) {
      mapServer("map1")
      
    }
    
    shinyApp(ui, server)