SymbolixAU / googleway

R Package for accessing and plotting Google Maps
http://symbolixau.github.io/googleway/
Other
232 stars 46 forks source link

Example request: Using google_place_autocomplete for a form #226

Open Nirzaree opened 3 years ago

Nirzaree commented 3 years ago

There are examples for using the google_place_autocomplete for a given string input and that works fine. However, for a continuously updating dropdown, we would need to call the function as the user keeps typing in the field, and it is not very clear as to how to achieve this.

I am trying to build an address autocompletion field in a form on shiny app. Currently I am using some javascript code to achieve the same but would be happy to have a simpler more elegant solution by using the googleway's autocomplete function.

Thanks.

dcooley commented 3 years ago

You might be able to follow the solution here? - https://github.com/daqana/dqshiny/issues/7#issuecomment-562131296

related - https://github.com/SymbolixAU/googleway/issues/213

chalioui commented 3 years ago

The solution is not working if we clear the text address and try typing a new one

dcooley commented 8 months ago

here's a basic example of using a Javascript solution, rather than googleway::google_places_autocomplete()


library(googleway)
library(shiny)
library(shinydashboard)

set_key(secret::get_secret("GOOGLE"))

ui <- shinydashboard::dashboardPage(
  header = shinydashboard::dashboardHeader()
  , sidebar = shinydashboard::dashboardSidebar()
  , body = shinydashboard::dashboardBody(
      shiny::textInput(inputId = "searchInput", label = "Search")
      , shiny::tags$head(
        shiny::tags$script(
          "
            var checkExists = setInterval(function() {
            // in the abasence of clever callback functions, I'm using a interval check to make sure `google` is loaded

            const options = {
              componentRestrictions: { country: 'au'}
            };

            // requires `google` to exist, so we need to load the js library. This is done automatically if you
            // also add a `googleway::google_map()` to the shiny
            // 
            var autoComplete = new google.maps.places.Autocomplete(searchInput, options);
            autoComplete.addListener('place_changed', function() {
              autoComplete.setFields(['place_id', 'geometry', 'name']);
              var place = autoComplete.getPlace();
              Shiny.setInputValue('placeAutocomplete', place.geometry);
            });

          }, 100);
          "
        )
      )
      , googleway::google_mapOutput(
        outputId = "map"
        , width = "100%"
        , height = "600px"
      )
  )
)

server <- function(input, output, session) {

  output$map <- googleway::renderGoogle_map(
    google_map(libraries = "places")
  )

  observeEvent(input$placeAutocomplete, {
    print(input$placeAutocomplete)
  })

}

shinyApp(ui, server)
RayShao01010010 commented 8 months ago

Is there a way to run use the autocomplete without needing of rendering a map?

dcooley commented 8 months ago

yeah just replace the googleway::google_mapOutput with a call to the javascript libarary

shiny::tags$script(
        src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places"
      )

or you can hide the map in the UI

just be aware that if you call the js library directly, AND use googleway::google_map() somewhere else, you may get a conflict as the library will have been called twice.

dcooley commented 7 months ago

A slight modification to correctly use async defer

ui <- shinydashboard::dashboardPage(
  header = shinydashboard::dashboardHeader()
  , sidebar = shinydashboard::dashboardSidebar()
  , body = shinydashboard::dashboardBody(
    shiny::textInput(inputId = "searchInput", label = "Search")
    , shiny::tags$head(
      shiny::tags$script(
        "
        function initialiseAddressPicker() {
            const options = {
              componentRestrictions: { country: 'au'}
            };

            // requires `google` to exist, so we need to load the js library. This is done automatically if you
            // also add a `googleway::google_map()` to the shiny
            var autoComplete = new google.maps.places.Autocomplete(searchInput, options);
            autoComplete.addListener('place_changed', function() {
              autoComplete.setFields(['place_id', 'geometry', 'name']);
              var place = autoComplete.getPlace();
              Shiny.setInputValue('placeAutocomplete', place.geometry);
            });
        }
          "
      )
      , HTML(
        '<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&libraries=places&callback=initialiseAddressPicker" async defer></script>'
      )
    )
  )
)

server <- function(input, output, session) {

  observeEvent(input$placeAutocomplete, {
    print(input$placeAutocomplete)
  })

}

shinyApp(ui, server)
dcooley commented 7 months ago

see also