Shiny中将响应式数据转换为Kable表格渲染失败如何解决
问题根因
renderTable()仅支持接收数据框对象作为输入,你调用kbl()生成的表格属于knitr_kable/kableExtra类的HTML对象,无法被renderTable强制转换为数据框,因此触发报错。
完整修改方案
你需要修改输出组件类型、渲染函数,同时补充月度/年度的过滤逻辑,修改后的完整可运行代码如下:
# Libraries library(shiny) library(ggplot2) library(shinythemes) library(DT) library(kableExtra) library(lubridate) library(tidyverse) ui <- fluidPage( theme = shinytheme("spacelab"), ## Application Title titlePanel("2021 Budgeting & Finances"), tags$em("By:"), tags$hr(), navbarPage("", id = "Budget", tabPanel("Data Entry", div(class = "outer", # Sidebar Layout sidebarLayout( sidebarPanel( selectInput("Name", label = "Name:", choices = c("","Jack", "Jill")), selectInput("Bucket", label = "Item Bucket:", choices = c("","Essential", "Non-Essential", "Savings", "Rent/Bills", "Trip", "Other")), textInput("Item", label = "Item Name:", placeholder = "Ex: McDonald's"), shinyWidgets::numericInputIcon("Amount", "Amount:", value = 0, step = 0.01, min = 0, max = 1000000, icon = list(icon("dollar"), NULL)), dateInput("Date", label = "Date", value = Sys.Date(), min = "2021-05-01", max = "2022-12-31", format = "M-d-yyyy"), actionButton("Submit", "Submit", class = "btn btn-primary"), downloadButton("Download", "Download")), mainPanel( DTOutput("PreviewTable") ) ) ) ), tabPanel("Monthly Budget", htmlOutput("MonthlyTable") ), tabPanel("Budget to Date", htmlOutput("YearTable") ) ) ) server <- function(input, output, session) { ## SAVE DATA # Set Up Empty DF df <- tibble("Name" = character(), "Date" = Date(), "Category" = character(), "Amount" = numeric(), "Description" = character()) ReactiveDf <- reactiveVal(value = df) observeEvent(input$Submit, { if (input$Bucket == "" | input$Amount == 0 | is.na(input$Amount)) { return(NULL) } else { new_lines <- data.frame(Name = as.character(input$Name), Date = input$Date, Category = input$Bucket, Amount = input$Amount, Description = as.character(input$Item)) # 直接更新响应式变量,无需全局变量 ReactiveDf(rbind(ReactiveDf(), new_lines)) updateSelectInput(session, inputId = "Name", selected = "") updateSelectInput(session, inputId = "Bucket", selected = "") updateNumericInput(session, inputId = "Amount", value = 0) updateTextInput(session, inputId = "Item", value = "") } }) # 录入页预览用DT渲染,支持交互 output$PreviewTable <- renderDT({ ReactiveDf() }, options = list(pageLength = 10)) # 月度表格:过滤当月数据,用renderUI渲染kable output$MonthlyTable <- renderUI({ req(nrow(ReactiveDf()) > 0) ReactiveDf() %>% filter(year(Date) == year(Sys.Date()), month(Date) == month(Sys.Date())) %>% kbl() %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = T) }) # 年度表格:过滤当年数据,用renderUI渲染kable output$YearTable <- renderUI({ req(nrow(ReactiveDf()) > 0) ReactiveDf() %>% filter(year(Date) == year(Sys.Date())) %>% kbl() %>% kable_styling(bootstrap_options = c("striped", "hover", "condensed"), full_width = T) }) } shinyApp(ui = ui, server = server)
核心修改点说明
- 把月度、年度页的
tableOutput替换为htmlOutput,用来承载kable生成的HTML格式表格 - 用
renderUI替代原来的renderTable渲染kable对象,避免类型转换报错 - 日期字段存储为Date类型,配合lubridate包的
year()、month()函数实现月度、年度数据过滤 - 录入页预览表格改用
renderDT配合DTOutput,保证表格交互性,符合你原来的组件配置 - 去掉冗余的全局变量赋值操作,直接操作响应式变量
ReactiveDf即可实现数据更新
内容的提问来源于stack exchange,提问作者Jose
相关产品推荐
相关产品推荐

