【问题标题】:Shinydashboard: Google Places Autocomplete. InvalidValueError: not an instance of HTMLInputElementShinydashboard:谷歌地方信息自动完成。 InvalidValueError:不是 HTMLInputElement 的实例
【发布时间】:2019-07-17 19:08:23
【问题描述】:

我正在尝试将shinydashboard 放在一起,并将 Google 地方搜索框作为文本输入。下面的代码在常规的shiny 页面中运行,但在放入shinydashboard 时会引发InvalidValueError: not an instance of HTMLInputElement 错误。 (见下图)

我不确定为什么它可以在常规的 shiny 应用程序中工作,但 不能shinydashboard 中工作。

错误截图:

最小的可重现代码示例:

注意: 首先插入您的 Google API 密钥

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

#key <- "MyKey"
#set_key(key = key)
#google_keys()


ui<- shinydashboard::dashboardPage(
  dashboardHeader(title = "Look @ Console"),
  dashboardSidebar(list(sidebarMenuOutput("sideBar_menu_UI"))), 
  dashboardBody(
    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>"))
    ,uiOutput("tabContentUI")
  )
)



server <- function(input, output) {

  output$sideBar_menu_UI <- renderMenu({
    sidebarMenu(id = "sideBar_Menu",

                menuItem("Data Import", tabName="datatab", icon = icon("database")),
                conditionalPanel("input.sideBar_Menu=='datatab'", 
                                 shiny::radioButtons(inputId = "upload_custom_data", label = "Do You Want To Upload Your Own Data?",
                                                     choices  = c("Yes"=TRUE, "No"=FALSE), selected = FALSE, inline = TRUE),
                                 shiny::uiOutput("conditionalFileInputUI")),
                menuItem("AnotherMenu", tabName = "anotherMenu", icon = icon("list-ol")))
  }) 

  output$conditionalFileInputUI<- shiny::renderUI({
    if(input$upload_custom_data == TRUE){}
    if(input$upload_custom_data == FALSE){
      list(
        shiny::textInput(inputId = "my_address", label = "Search For Address", width = "350px"),
        shiny::actionButton(inputId = "add_btn", label = "Add To Dataset", icon = icon("plus"))
      )

    }
  })

  ### Output$Stuff Here
  output$anotherMenu_content<- shiny::renderText({"This is some text" })
  output$datatab_content<- shiny::renderUI({ list(shiny::uiOutput("full_address"), shiny::uiOutput("my_map")) })

  #### Tab Content UI Materials
  output$tabContentUI<- shiny::renderUI({
    shinydashboard::tabItems(
      shinydashboard::tabItem(tabName = "datatab", shiny::uiOutput("datatab_content")), 
      shinydashboard::tabItem(tabName = "anotherMenu", shiny::textOutput("anotherMenu_content"))
    )
  })

  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
    }
  })

  output$full_address <- renderText({
    if(!is.null(my_address())){
      paste0("The Fuller and Fixed Address is... ", my_address())
    }
  })

  output$my_map <- renderGoogle_map({
    my_address <- my_address()
    shiny::validate(
      need(my_address, "Address not available")
    )

    gdat <- google_geocode(address = my_address)
    my_coords <- geocode_coordinates(gdat)
    my_coords <- c(my_coords$lat[1], my_coords$lng[1])

    google_map(
      location = my_coords,
      zoom = 12,
      map_type_control = FALSE,
      zoom_control = FALSE,
      street_view_control = FALSE
    )
  })

}

shinyApp(ui, server)

我很想知道是否有人知道如何解决这个问题?我很感激任何反馈。先感谢您。

--先天

更新:

我还没有解决这个问题。但是,通过反复试验,我注意到如果我从server.R 文件中取出“搜索地址”输入并将原始HTML 放入UI 部分,我可以恢复一些功能。

将此代码放入 UI 会得到部分解决方案...(为格式化道歉)

  shinydashboard::dashboardSidebar(width = "400px",


list(shinydashboard::sidebarMenuOutput(outputId = "sideBar_menu_UI"),


 HTML('<div class="form-group shiny-input-container"> <label for="my_address">Type An Address</label> <input id="my_address" type="text" class="form-control" value=""/> </div>'))),

更新后的 UI 现在如下所示:

【问题讨论】:

    标签: javascript r shiny shinydashboard google-places


    【解决方案1】:

    我能够做到这一点的唯一方法是将渲染 sidebarMenu 背后的所有逻辑从 server.R 文件中取出并将其放入 ui.R 文件中。

    最终的工作解决方案是这样的:

    library(shiny)
    library(googleway)
    library(shinydashboard)
    
    #key <- "MyKey"
    #set_key(key = mygoogleapikey)
    #google_keys()
    
    
    ui<- shinydashboard::dashboardPage(
      dashboardHeader(title = "This Works"),
      dashboardSidebar(shinydashboard::sidebarMenu(id="sideBar_Menu",
                                                  menuItem("Data Import", tabName="datatab", icon = icon("database")),
                                                  conditionalPanel("input.sideBar_Menu=='datatab'",
                                                  shiny::radioButtons(inputId = "upload_custom_data", label = "Do You Want To Upload Your Own Data?", choices  = c("Yes"=TRUE, "No"=FALSE), selected = TRUE, inline = TRUE),
    
                                                  conditionalPanel("input.upload_custom_data == 'TRUE'",
                                                                   shiny::actionButton("go", "Go")),
    
                                                  conditionalPanel("input.upload_custom_data == 'FALSE'",
                                                                   textInput(inputId = "my_address", label = "Type An Address"),
                                                                   shiny::actionButton(inputId = "add_btn", label = "Add To Dataset", icon = icon("plus")))
    
    
                                                   ), # with outer conditional menu
                                                   menuItem("AnotherMenu", tabName = "anotherMenu", icon = icon("list-ol"))
      ) # with sidebar menu
      ),
    
      dashboardBody(
        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>"))
        ,uiOutput("tabContentUI")
        )
        )
    
    
    
    server <- function(input, output) {
    
    
    
    
      ### Output$Stuff Here
      output$anotherMenu_content<- shiny::renderText({"This is some text" })
      output$datatab_content<- shiny::renderUI({ list(shiny::uiOutput("full_address"), shiny::uiOutput("my_map")) })
    
      #### Tab Content UI Materials
      output$tabContentUI<- shiny::renderUI({
        shinydashboard::tabItems(
          shinydashboard::tabItem(tabName = "datatab", shiny::uiOutput("datatab_content")), 
          shinydashboard::tabItem(tabName = "anotherMenu", shiny::textOutput("anotherMenu_content"))
        )
      })
    
      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
        }
      })
    
      output$full_address <- renderText({
        if(!is.null(my_address())){
          paste0("The Fuller and Fixed Address is... ", my_address())
        }
      })
    
      output$my_map <- renderGoogle_map({
        my_address <- my_address()
        shiny::validate(
          need(my_address, "Address not available")
        )
    
        gdat <- google_geocode(address = my_address)
        my_coords <- geocode_coordinates(gdat)
        my_coords <- c(my_coords$lat[1], my_coords$lng[1])
    
        google_map(
          location = my_coords,
          zoom = 12,
          map_type_control = FALSE,
          zoom_control = FALSE,
          street_view_control = FALSE
        )
      })
    
    }
    
    shinyApp(ui, server)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-07
      • 1970-01-01
      • 2016-03-24
      • 2017-11-25
      • 1970-01-01
      • 2020-10-04
      • 1970-01-01
      相关资源
      最近更新 更多