javascript - Shinydashboard:Google 地点自动完成。 InvalidValueError:不是 HTMLInputElement 的实例

标签 javascript r shiny shinydashboard google-places

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

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

错误截图: enter image description here

最小可重现代码示例:

注意: 首先插入您的 Google API key

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 中可以得到部分解决方案......(对格式表示歉意)

  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>'))),

更新后的用户界面现在如下所示: Getting Closer Screenshot

最佳答案

我能够做到这一点的唯一方法是从 server.R 文件中获取渲染 sidebarMenu 背后的所有逻辑并将其放入 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)

关于javascript - Shinydashboard:Google 地点自动完成。 InvalidValueError:不是 HTMLInputElement 的实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54848254/

相关文章:

r - 更改 Shiny 的 dateRangeInput 中 "to"的语言

javascript - 如何迭代对象数组并将键值作为字符串的一部分返回

javascript - 如何将组件的值传递给其父组件?

r - 我可以使用因子作为搜索并替换 mutate 中的值吗?

javascript - R Shiny HTML UI 无法正常工作

r - 以 Shiny 而不是错误显示空白图

javascript - JavaScript 的执行是否会延迟到 CSSOM 构建完成?

javascript - Mongoose 数组和 Javascript 数组的区别

r - 无法安装flextable

r - for循环中跳过错误