Shiny应用传numericInput到gt::cols_width报input对象未找到错误
问题背景
开发简易Shiny应用,需要将numericInput控件接收的用户输入传入gt包cols_width()函数参数,实现表格第一列宽度自定义。运行代码时触发Error: object 'input' not found报错,先后尝试{input$colpad}、.(input$colpad)写法均未解决问题。
核心报错代码段:
output$table <- render_gt( reactive_tab() %>% gt() %>% cols_width( 1 ~ px(input$colpad) ) )
预期效果:
完整可复现初始代码:
library(data.table) library(shiny) library(gt) library(shinyscreenshot) data <- gtcars %>% head(10) %>% select(mfr, model, msrp) ui <- navbarPage("Y u no pad??", tabPanel("Table", icon = icon("table"), sidebarLayout( sidebarPanel( selectInput("input", label = "Choose mfr", choices = c("All", data$mfr)), numericInput("colpad", label = "First Column Padding", min = 1, max = 10000, value = 150), screenshotButton(selector="#table", label = 'Download Png', filename = 'screenshot'), ), mainPanel( gt_output("table") ) ) ) ) server <- function(input, output, session) { reactive_tab <- reactive({ d <- data if(input$input != "All") d <- subset(d, cyl == input$input) d }) output$table <- render_gt( reactive_tab() %>% gt() %>% cols_width( 1 ~ px(input$colpad) ) ) } shinyApp(ui, server)
报错原因
cols_width()中使用~定义的公式是在gt构建的表格数据掩码环境中求值,该环境默认只会识别表格自带的列字段,不会主动向上访问Shiny的input响应式对象,因此直接在公式内部写input$colpad会提示找不到对象。
另外初始代码还存在两个隐性问题:
- 构造筛选数据时,子集条件写的是
cyl == input$input,但预处理的数据集仅保留了mfr、model、msrp三列,不存在cyl字段,且下拉选项是mfr的取值,筛选字段和选项不匹配,选择非All选项时也会触发报错; - 选择控件的inputId命名为
input,和Shiny内置的input对象重名,容易引发命名冲突。
修复方案
核心解决思路是让cols_width()能正确获取到Shiny输入值,两种写法均可:
- 在
render_gt的执行环境中提前提取input$colpad的值,再传入公式,让公式从定义环境中读取该值; - 用
!!运算符直接将输入值注入到公式参数中,跳过gt的掩码环境查找。
同时修正筛选字段匹配问题、优化控件id命名即可。
修复后的完整可运行代码:
library(data.table) library(shiny) library(gt) library(shinyscreenshot) data <- gtcars %>% head(10) %>% select(mfr, model, msrp) ui <- navbarPage("Y u no pad??", tabPanel("Table", icon = icon("table"), sidebarLayout( sidebarPanel( # 重命名inputId避免和内置input对象冲突 selectInput("mfr_select", label = "Choose mfr", choices = c("All", unique(data$mfr))), numericInput("colpad", label = "First Column Padding", min = 1, max = 10000, value = 150), screenshotButton(selector="#table", label = 'Download Png', filename = 'screenshot'), ), mainPanel( gt_output("table") ) ) ) ) server <- function(input, output, session) { reactive_tab <- reactive({ d <- data # 修正筛选字段,和下拉选项匹配 if(input$mfr_select != "All") d <- subset(d, mfr == input$mfr_select) d }) output$table <- render_gt({ reactive_tab() %>% gt() %>% cols_width( # 用!!直接注入输入值,无需提前赋值 1 ~ px(!!input$colpad) ) }) } shinyApp(ui, server)
内容的提问来源于stack exchange,提问作者RL_Pug
相关产品推荐
相关产品推荐

