googleway icon indicating copy to clipboard operation
googleway copied to clipboard

Example request: Using google_place_autocomplete for a form

Open Nirzaree opened this issue 4 years ago • 7 comments

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.

Nirzaree avatar Sep 25 '20 17:09 Nirzaree

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

dcooley avatar Sep 27 '20 23:09 dcooley

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

chalioui avatar Feb 10 '21 17:02 chalioui

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)

dcooley avatar Nov 07 '23 23:11 dcooley

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

RayShao01010010 avatar Nov 08 '23 04:11 RayShao01010010

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 avatar Nov 08 '23 04:11 dcooley

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 avatar Nov 08 '23 23:11 dcooley

see also

  • https://stackoverflow.com/questions/53347495/r-shiny-map-search-input-box?noredirect=1&lq=1
  • https://stackoverflow.com/questions/54848254/shinydashboard-google-places-autocomplete-invalidvalueerror-not-an-instance-o

dcooley avatar Nov 09 '23 00:11 dcooley