Shiny for R DT:如何读取/保留页面长度和列可见性

问题描述 投票:0回答:3

我对这个应用程序还很陌生,所以如果很明显,请原谅我。我有一个可以根据地图中心重新计算的数据表。效果很好。但是我想阅读并保留(保留)某些设置:即页面长度和列可见性。目前,如果用户更改为每页 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)

})
r datatables shiny
3个回答
3
投票

好的,看看下面的例子,它应该保留你的分页。请注意,我添加了一个按钮,该按钮应该从头开始将所有内容呈现为第一个值。请查看客户端表示例和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)

1
投票

我有类似的需求,这些是我的发现:

  • 要使用从当前行计算的方法自动监视页面长度值,将需要一个反应式表达式(而不是按钮)。然而,这不起作用,因为当表刷新时,当前行将变为无效,这会阻止反应式表达式评估(它会简单地停止,您不能通过检查 null 来跳过它)

  • 您原来的解决方案实际上可以更好地工作,但我们需要更具体,观察页面长度变化而不是整个状态。

    observeEvent(input$dataviewer_state$length
    。您的问题是 NULL 触发了事件。也许是闪亮的更新,现在observeEvent默认不会由NULL触发。请参阅
    ignoreNULL
     中有关 

    observeEvent
  • 的帮助
  • 当使用stateSave = TRUE时,它将在html5本地存储中保存状态,这将在整个会话中保留,即使R全局环境为空,这可能会让用户感到困惑。我使用

    stateDuration = -1
    使用会话存储而不是本地存储。


0
投票

添加一个

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()) })
© www.soinside.com 2019 - 2024. All rights reserved.