如何避免点击R Shiny的FileInput浏览按钮时页面跳转到顶部
这个问题是Shiny封装fileInput组件时的底层交互bug,点击模拟的「Browse」按钮时会触发不必要的页面重定位,导致滚动条复位到顶部,有两种常用的修复方案:
方案1:添加自定义JS直接修复跳转问题
在你的ui代码的fluidPage开头插入一段JS代码,拦截fileInput按钮的点击默认行为即可,不需要修改原有业务逻辑,修改后的完整示例如下:
library(shiny) ui <- fluidPage( # 插入修复跳转的JS代码 tags$head( tags$script(HTML(" $(document).on('click', '.input-group-btn .btn', function(e) { e.preventDefault(); }); ")) ), sidebarLayout( sidebarPanel( selectInput( inputId = "numSessions", label = "Number of Sessions", choices = c("1 Session" = 1, "2 Sessions" = 2, "3 Sessions" = 3, "10 Sessions"= 10) ), conditionalPanel( condition = "input.numSessions == 1", fileInput(inputId = "s1", label = "s1 upload") ), conditionalPanel( condition = "input.numSessions == 2", fileInput(inputId = "s1", label = "s1 upload"), fileInput(inputId = "s2", label = "s2 upload") ), conditionalPanel( condition = "input.numSessions == 3", fileInput(inputId = "s1", label = "s1 upload"), fileInput(inputId = "s2", label = "s2 upload"), fileInput(inputId = "s3", label = "s3 upload"), ), conditionalPanel( condition = "input.numSessions == 10", fileInput(inputId = "s1", label = "s1 upload"), fileInput(inputId = "s2", label = "s2 upload"), fileInput(inputId = "s3", label = "s3 upload"), fileInput(inputId = "s4", label = "s4 upload"), fileInput(inputId = "s5", label = "s5 upload"), fileInput(inputId = "s6", label = "s6 upload"), fileInput(inputId = "s7", label = "s7 upload"), fileInput(inputId = "s8", label = "s8 upload"), fileInput(inputId = "s9", label = "s9 upload"), fileInput(inputId = "s10", label = "s10 upload") ) ), mainPanel() ) ) server <- function(input, output) {} shinyApp(ui = ui, server = server)
方案2:改用动态渲染UI的写法,既简化代码也能规避该问题
你现在写多组conditionalPanel的方式冗余度很高,如果后续要扩展到20个会话会非常难维护,改用renderUI动态生成对应数量的fileInput,同时也能避开跳转bug,完整示例如下:
library(shiny) ui <- fluidPage( sidebarLayout( sidebarPanel( selectInput( inputId = "numSessions", label = "Number of Sessions", # 可直接扩展到20个选项,不需要手动加conditionalPanel choices = setNames(1:20, paste0(1:20, " Sessions")) ), # 动态生成上传组件的容器 uiOutput("upload_uis") ), mainPanel() ) ) server <- function(input, output) { output$upload_uis <- renderUI({ n <- as.integer(input$numSessions) # 循环生成对应数量的fileInput lapply(1:n, function(i) { fileInput(inputId = paste0("s", i), label = paste0("s", i, " upload")) }) }) } shinyApp(ui = ui, server = server)
内容的提问来源于stack exchange,提问作者anorlondo
相关产品推荐
相关产品推荐

