我对这个应用程序还很陌生,所以如果很明显,请原谅我。我有一个可以根据地图中心重新计算的数据表。效果很好。但是我想阅读并保留(保留)某些设置:即页面长度和列可见性。目前,如果用户更改为每页 20 个条目并移动地图,它会使用默认页面长度和列可见性(在按钮中使用 colvis)重新呈现它。我认为我可以将它存储在某个变量中并在重新渲染表时检索它,但不确定如何从选项内部读取。 它是在 R Studio 中为 Shiny 构建的 有什么想法吗?
编辑:我使用选项 stateSave = TRUE 获取有关页面长度和列可见性的数据,然后读取 input$Btable_state$length (我也可以读取哪些列可见),但现在我的问题是:重新渲染时对于表,它首先变为 NULL 值,覆盖 input$Btable_state 中存储的任何内容。仅当它通过过滤器更改而不是通过重新呈现表本身的活动更改时,我如何才能捕获和影响它?
EDIT2:由于我的应用程序需要连接到我的谷歌表格,因此无法复制,可以在 Github (vnijs/dt_state) 的以下示例中进行尝试。如何在对列重新排序时保留非默认页面长度(例如 50)(但不将操作链接到 selectizeInput,仅保留最后的正确状态)
#ui.r
shinyUI(fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("ui_view_vars"),
tags$a(id = "refresh", href = "#", class = "action-button",
list(icon("refresh"), "Clear state"),
onclick = "window.location.reload();")
),
mainPanel(
tabPanel("View", DT::dataTableOutput("dataviewer")
)
)
)
))
#server.r
library(shiny)
library(DT)
dat <- iris
## store state in global environment for now
if (!exists("r_state")) r_state <- list()
## Only used from a 'clean' start
r_state$dataviewer_search_columns <- list("","2.5...4","","","[\"setosa\"]")
shinyServer(function(input, output, session) {
output$ui_view_vars <- renderUI({
vars <- colnames(dat)
## using selectizeInput with drag_drop and DT
selectizeInput("view_vars", "Select variables to show:", choices = vars,
selected = vars, multiple = TRUE,
options = list(plugins = list('remove_button', 'drag_drop')))
})
## make nested list
mknl <- function(x) list(search = x)
observeEvent(input$dataviewer_search_columns, {
r_state$dataviewer_search_columns <<- input$dataviewer_search_columns
})
observeEvent(input$dataviewer_state, {
r_state$dataviewer_state <<- input$dataviewer_state
})
observeEvent(input$refresh, {
r_state <<- list()
})
output$dataviewer <- DT::renderDataTable({
req(input$view_vars)
search <- r_state$dataviewer_state$search$search
if (is.null(search)) search <- ""
DT::datatable(iris[,input$view_vars],
filter = list(position = "top", clear = TRUE),
rownames = FALSE,
selection = "none",
options = list(
stateSave = TRUE,
searchCols = lapply(r_state$dataviewer_search_columns, mknl),
search = list(search = search, regex = TRUE),
order = {if (is.null(r_state$dataviewer_state$order)) list()
else r_state$dataviewer_state$order},
processing = FALSE
),
callback = DT::JS("$(window).unload(function() { table.state.clear(); })")
)
})
output$tbl_col_search <- renderPrint(input$dataviewer_search_columns)
})
好的,看看下面的例子,它应该保留你的分页。请注意,我添加了一个按钮,该按钮应该从头开始将所有内容呈现为第一个值。请查看客户端表示例和2.2 DataTables信息页面。
rm(list=ls())
library(shiny)
library(DT)
ui <- basicPage(actionButton("Go","Go"),DT::dataTableOutput('x1'))
server <- shinyServer(function(input, output, session){
tableparams <- reactiveValues()
observeEvent(input$Go,{
if(is.null(input$x1_rows_current)){
tableparams$pageLength <- 5
}
else{
tableparams$pageLength <- length(input$x1_rows_current)
}
})
my_data <- eventReactive(input$Go,{iris})
output$x1 = DT::renderDataTable(datatable(my_data(),options = list(pageLength = tableparams$pageLength)))
})
shinyApp(ui = ui, server = server)
我有类似的需求,这些是我的发现:
要使用从当前行计算的方法自动监视页面长度值,将需要一个反应式表达式(而不是按钮)。然而,这不起作用,因为当表刷新时,当前行将变为无效,这会阻止反应式表达式评估(它会简单地停止,您不能通过检查 null 来跳过它)
您原来的解决方案实际上可以更好地工作,但我们需要更具体,观察页面长度变化而不是整个状态。
observeEvent(input$dataviewer_state$length
。您的问题是 NULL 触发了事件。也许是闪亮的更新,现在observeEvent默认不会由NULL触发。请参阅 ignoreNULL
中有关 observeEvent
当使用stateSave = TRUE时,它将在html5本地存储中保存状态,这将在整个会话中保留,即使R全局环境为空,这可能会让用户感到困惑。我使用
stateDuration = -1
使用会话存储而不是本地存储。添加一个
JS callback
,在绘制时检索 page.info
。观察事件并分配给 reactiveVal()
,这会使 DT 无效并保留 DT pageLength
。
makeDatatable <- function(df) {
DT::datatable(
data = df,
callback = DT::JS(
"table.on('draw.dt', function() {
var page = table.page.info();
Shiny.onInputChange('page_info', page);
});",
options = list(paging = TRUE,
pageLength = page_len,
lengthMenu = c(10, 20, 50, 100))
)}
)
page_len <- shiny::reactiveVal(13) # default
observeEvent(input$page_info, {
page_len(input$page_info$length)
})
output$dt <- DT::renderDT(
expr = { makeDatatable(df, page_len()) })