在构建数据表时,我在组合两个功能时遇到了问题:
两者分开工作,但不能一起工作。如果我取消选中菜单输入中的列,数据就会消失 - 就像应用过滤器一样,没有找到数据。我该如何解决这个问题?
library(shiny)
runApp(list(ui=(fluidPage(
pageWithSidebar(
headerPanel('Title'),
sidebarPanel(
helpText('Text about the table'),
checkboxInput('columns','I want to select the columns' , value = FALSE),
conditionalPanel(
condition= "input.columns == true",
checkboxGroupInput('show_vars', 'Select the columns that you want to see:', names(iris[1:4]),
selected = names(iris[1:4]))
),
downloadButton('downloadData', 'Download'),width = 3
),
mainPanel(
tags$head(tags$style("tfoot {display: table-header-group;}")),
dataTableOutput("mytable1"),width = 9
)
))
)
,
server=(function(input, output) {
library(ggplot2)
library(XLConnect)
#DATA
tabel<- reactive({
iris[,c(input$show_vars,"Species"), drop = FALSE]
})
# OUTPUT
output$mytable1 = renderDataTable({
tabel()},
options = list(
aoColumns = list(list(bSearchable = FALSE), list(bSearchable = FALSE),list(bSearchable = FALSE),
list(bSearchable = FALSE),list(bSearchable = TRUE)),
bFilter=1, bSortClasses = 1,aLengthMenu = list(c(10,25,50, -1), list('10','25', '50', 'Todas')),iDisplayLength = 10
)
)
output$downloadData <- downloadHandler(
filename = function() { paste('tabela_PSU','.xlsx', sep='') },
content = function(file){
fname <- paste(file,"xlsx",sep=".")
wb <- loadWorkbook(fname, create = TRUE)
createSheet(wb, name = "Sheet1")
writeWorksheet(wb, tabel(), sheet = "Sheet1")
saveWorkbook(wb)
file.rename(fname,file)
},
)
})
))
答案 0 :(得分:2)
问题在于根据iris
过滤数据input$show_vars
,您正在更改DataTable的列数。
但是,您已经定义了固定 aoColumns
选项,这意味着您的DataTable有五列(四个不可搜索,一个可搜索)。
因此,当您取消选择任何复选框输入时,过滤后的数据与指定的选项不匹配。结果,没有显示任何内容。
也就是说,虽然DataTable中的数据是被动,但选项无反应。
如果仔细阅读renderDataTable
's document,您会发现可以将两种类型的变量传递给options
参数:
options要传递给DataTables的初始化选项列表,或返回此类列表的函数。
区别在于:
options
指定为列表,则Shiny会假定options
已修复;但是,由于您是基于input$show_vars
动态过滤数据,因此应动态更改aoColumns
的选项。 options
的参数传递,Shiny将知道options
也是被动的。因此,当数据(在您的情况下,options
封装在名为data.frame
的反应变量中)更新时,Shiny也会更新tabel
。您可能已经知道反应变量本身就是功能。它们在被动环境中进行评估,在评估时,它们返回数据的当前状态/值。这就是您将tabel()
而不是tabel
传递给renderDataTable
的原因。
然后,解决方案是将整个options
列表包装成一个反应变量(因此也是一个函数)。具体来说,我们想要动态设置aoColumns
选项,以便bSearchable
切换的数量与DataTable中显示的列数相匹配。
下面我只显示更新的server
部分,因为在UI部分中无需更改任何内容。
shinyServer(function(input, output) {
library(ggplot2)
library(XLConnect)
#DATA
tabel<- reactive({
iris[,c(input$show_vars,"Species"), drop = FALSE]
})
# wrap the `options` into a reactive variable (hence a function) so that it will
# be evaluated dynamically when the data changes as well.
# `dt_options` is reactive in the sense that it will reflect the number of rows
# visible based on the checkboxInput selections.
dt_options <- reactive({
# dynamically create options for `aoColumns` depending on how many columns are selected.
toggles <- lapply(1:length(input$show_vars), function(x) list(bSearchable = F))
# for `species` columns
toggles[[length(toggles) + 1]] <- list(bSearchable = T)
list(
aoColumns = toggles,
bFilter = 1, bSortClasses = 1,
aLengthMenu = list(c(10,25,50, -1), list('10','25', '50', 'Todas')),
iDisplayLength = 10
)
})
# OUTPUT
output$mytable1 = renderDataTable({
tabel()},
options = dt_options
)
output$downloadData <- downloadHandler(
filename = function() { paste('tabela_PSU','.xlsx', sep='') },
content = function(file){
fname <- paste(file,"xlsx",sep=".")
wb <- loadWorkbook(fname, create = TRUE)
createSheet(wb, name = "Sheet1")
writeWorksheet(wb, tabel(), sheet = "Sheet1")
saveWorkbook(wb)
file.rename(fname,file)
},
)
})
(请注意,我将UI部分和服务器部分分为ui.R
和server.R
。)