Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pin doesn't load when using google_map_update #274

Closed
cwilligv opened this issue Sep 2, 2024 · 4 comments
Closed

Pin doesn't load when using google_map_update #274

cwilligv opened this issue Sep 2, 2024 · 4 comments

Comments

@cwilligv
Copy link

cwilligv commented Sep 2, 2024

I'm using googleway in an app that has an autocomplete search box outside the map. The first time the app loads and you search for an address it updates the map but it doesn't place the pin on the map, however, after one refreshes the page and search for an address again it works fine and the pin is placed. I've been able to reproduce the error with the following reprex below. Note that it needs to be run with the browser's developer tools open and option 'Disable cache' checkbox activated so it simulates the first load of the page. I think it has to do with the library loading process at start but I'm not sure. Any ideas I could try?

library(shiny)
library(googleway)

key <- "your key"
set_key(key = key)

ui <- shiny::basicPage(
  
  div(
    textInput(inputId = "my_address", label = "Type An Address")
    ,textOutput(outputId = "full_address")
    ,actionButton(inputId = "btn", "Search")
    ,HTML(paste0(" <script> 
                function initAutocomplete() {

                 var autocomplete =   new google.maps.places.Autocomplete(document.getElementById('my_address'),{types: ['geocode']});
                 autocomplete.setFields(['address_components', 'formatted_address',  'geometry', 'icon', 'name']);
                 autocomplete.addListener('place_changed', function() {
                 var place = autocomplete.getPlace();
                 if (!place.geometry) {
                 return;
                 }

                 var addressPretty = place.formatted_address;
                 var address = '';
                 if (place.address_components) {
                 address = [
                 (place.address_components[0] && place.address_components[0].short_name || ''),
                 (place.address_components[1] && place.address_components[1].short_name || ''),
                 (place.address_components[2] && place.address_components[2].short_name || ''),
                 (place.address_components[3] && place.address_components[3].short_name || ''),
                 (place.address_components[4] && place.address_components[4].short_name || ''),
                 (place.address_components[5] && place.address_components[5].short_name || ''),
                 (place.address_components[6] && place.address_components[6].short_name || ''),
                 (place.address_components[7] && place.address_components[7].short_name || '')
                 ].join(' ');
                 }
                 var address_number =''
                 address_number = [(place.address_components[0] && place.address_components[0].short_name || '')]
                 var coords = place.geometry.location;
                 //console.log(address);
                 Shiny.onInputChange('jsValue', address);
                 Shiny.onInputChange('jsValueAddressNumber', address_number);
                 Shiny.onInputChange('jsValuePretty', addressPretty);
                 Shiny.onInputChange('jsValueCoords', coords);});}
                 </script> 
                 <script src='https://maps.googleapis.com/maps/api/js?key=", key,"&libraries=places&callback=initAutocomplete' async defer></script>"))
    ,google_mapOutput(outputId = "my_map")
  )
  
)

server <- function(input, output) {
  
  my_address <- reactive({
    if(!is.null(input$jsValueAddressNumber)){
      if(length(grep(pattern = input$jsValueAddressNumber, x = input$jsValuePretty ))==0){
        final_address<- c(input$jsValueAddressNumber, input$jsValuePretty)
      } else{
        final_address<- input$jsValuePretty
      }
      final_address
    }
  })
  
  observeEvent(input$btn, {
    # browser()
    my_address <- my_address()
    not_a_df <- google_geocode(address = my_address)
    my_coords <- geocode_coordinates(not_a_df)
    my_coords <- data.frame(lat = as.numeric(my_coords$lat[1]), lng = as.numeric(my_coords$lng[1]))
    
    googleway::google_map_update(map_id = "my_map") %>%
      # clear_markers() %>%
      googleway::add_markers(
        data = my_coords,
        lat = "lat",
        lon = "lng",
        update_map_view = T
      ) %>% 
      googleway::google_map_view(location = c(my_coords$lat, my_coords$lng), zoom = 19)
  })
  
  output$full_address <- renderText({
    if(!is.null(my_address())){
      my_address()
    }
  })
  
  output$my_map <- renderGoogle_map({
    google_map(
      location = c(-27.481080541187133, 153.0122871294947),
      zoom = 16,
      map_type_control = FALSE,
      zoom_control = FALSE,
      street_view_control = FALSE
    )
  })
  
}

shinyApp(ui, server)

For example: searching for this address 25 Lang Street, Sunnybank Hills returns this
image

The js errors in the console are:

  • InvalidValueError: setMap: not an instance of Map; and not an instance of StreetViewPanorama
  • InvalidValueError: setCenter: not a LatLng or LatLngLiteral with finite coordinates: in property lat: not a number

Any ideas would be much appreciated.

@dcooley
Copy link
Collaborator

dcooley commented Sep 3, 2024

notes:

  • example from https://stackoverflow.com/a/54848042/5977215
  • No need for geocode() because you're returning the coordinates from within the autocomplete function (autocomplete.setFields([ geometry, ... ]))
  • including the api call <script src='https://maps.googleapis.com/maps/api/ is causing the "You have included the api multiple times" error, because the api is loaded automatically when you call google_map(). related issue
    • An interim solution for this is only define autocomplete when google exists (inside a setInterval())
  • There are other 'deprecation' warnings that I'm addressing as part of 3.0.0; but I've been slow on this...

I've stripped down your example; you can see the output of the two print statements to see all the values returned from the search

library(shiny)
library(googleway)

key <- "key"
set_key(key = key)

ui <- shiny::basicPage(

  div(
    textInput(inputId = "my_address", label = "Type An Address")
    , actionButton(inputId = "btn", "Search")
    , shiny::tags$head(
      shiny::tags$script(
        '
        var mapExists = setInterval(function() {

          if(typeof google !== "undefined") {
            clearInterval(mapExists)

            var autocomplete = new google.maps.places.Autocomplete(document.getElementById("my_address"));
            autocomplete.addListener("place_changed", function() {
               autocomplete.setFields(["place_id", "geometry", "name"]);
               var place = autocomplete.getPlace();

               Shiny.setInputValue("jsPlaceAutocomplete", place);
             });

          }

        }, 100);
        '
      )
    )
    ,google_mapOutput(outputId = "my_map")
  )
)

server <- function(input, output) {

  observeEvent(input$jsPlaceAutocomplete, {
    print(input$jsPlaceAutocomplete)
    
    res <- input$jsPlaceAutocomplete
    
    df <- data.frame(
      lng = res$geometry$location$lng
      , lat = res$geometry$location$lat
    )
    
    
    googleway::google_map_update(map_id = "my_map") %>%
      googleway::add_markers(
        data = df,
        lat = "lat",
        lon = "lng",
        update_map_view = T
      )
  })

  observeEvent(input$btn, {
    print(input$jsPlaceAutocomplete)
  })

  output$my_map <- renderGoogle_map({
    google_map(
      location = c(-27.481080541187133, 153.0122871294947),
      zoom = 16,
      map_type_control = FALSE,
      zoom_control = FALSE,
      street_view_control = FALSE
    )
  })

}

shinyApp(ui, server)

@cwilligv
Copy link
Author

cwilligv commented Sep 3, 2024

Thanks @dcooley Dave for taking the time. Exciting news about v3.0.0!! looking forward to it :)
I've run your code and it solved the api multiple times error, that's great!
However, the issue I have is at first load of the app, when I run this in google cloud run the first time I hit the app it throws the error below and the search bar doesn't respond to typing an address, resulting in not being able to get a lat lon for it.

I was able to replicate this error by using the browser's dev tools and setting the option "Disable cache" on under the network menu. Note that this option only gets applied while dev tools is open.

image

If I reload the app (page refresh) then I don't get this error and the app works as expected.
Is there a way to change the library loading process differently? Maybe load the libraries from local folder in the project?

@dcooley
Copy link
Collaborator

dcooley commented Sep 4, 2024

I've updated master branch, and the UI code, with a couple more checks for undefined "google". Let me know if these work for you?

This works for me without console errors, with 'disable cache' checked.

ui <- shiny::basicPage(
  
  div(
    textInput(inputId = "my_address", label = "Type An Address")
    , actionButton(inputId = "btn", "Search")
    , shiny::tags$head(
      shiny::tags$script(
        '
        var mapExists = setInterval(function() {

          if(typeof google !== "undefined") {
            
            if(typeof google.maps !== "undefined") {
              
              clearInterval(mapExists);
  
              var autocomplete = new google.maps.places.Autocomplete(document.getElementById("my_address"));
              
              autocomplete.addListener("place_changed", function() {
                 autocomplete.setFields(["place_id", "geometry", "name"]);
                 var place = autocomplete.getPlace();
  
                 Shiny.setInputValue("jsPlaceAutocomplete", place);
               });
            }
          }

        }, 100);
        '
      )
    )
    ,google_mapOutput(outputId = "my_map")
  )
)

@cwilligv
Copy link
Author

cwilligv commented Sep 8, 2024

Hi @dcooley ,
This worked exactly as we needed. I have now integrated this on our app and it's working fine with no errors.

Thank you very much for your support here.

Looking forward to version 3.0

@cwilligv cwilligv closed this as completed Sep 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants