I am trying to write a Shiny app that only updates ONLY the data that is presented to the user by DT. I can do this outside of a Shiny module (below), but when I wrap this code in a Shiny module I lose the ability to query the state of the table.
How can I access the state of a DT once it's been wrapped in a module?
This is the non-Shiny module code that works.
#' This example is based on the Github issue #359
#' https://github.com/rstudio/DT/issues/359
#' problem statement: cannot access the state of a DT to
#' update only the rows which the user is currently viewing
#' and wrap this function in a module
#' credit: Aaron Berg <aaron@rstudio.com> for getting this to
#' work properly
library(shiny)
library(DT)
library(dplyr)
shinyApp(
ui = fluidPage(
fluidRow(
column(2, actionButton('upper', 'Upper Case')),
column(12, DT::dataTableOutput('foo'))
),
fluidRow(
column(12, verbatimTextOutput('info'))
)
),
server = function(input, output, session) {
df <- tibble(letter = letters)
n = nrow(df)
df$ID = seq_len(n)
loopData = reactive({
input$upper
#' print stuff to the console
print(isolate(input$foo_state$start))
print(isolate(input$foo_state$length))
if(is.null(isolate(input$foo_state$length))){
start <- 0
end <- 0
} else{
start <- (isolate(input$foo_state$start) + 1)
end <- isolate(input$foo_state$start +
ifelse(is.null(input$foo_state$length),
1,
input$foo_state$length))
if (end >= n) {
# prints end of the current users DT
cat(paste("end of current frame: ", end, "\n"))
end <- start + (n %% start)
}
}
df$letter[start:end] <<- toupper(df$letter[start:end])
df
})
observeEvent(input$foo_state, {
output$info = renderPrint(str(input$foo_state))
})
output$foo = DT::renderDataTable(datatable(isolate(loopData()),
options = list(stateSave = TRUE)))
proxy = dataTableProxy('foo')
observe({
replaceData(proxy, loopData(), resetPaging = FALSE)
})
}
)
This is the attempt at a Shiny module that does not work.
#' This example is based on the Github issue #359
#' https://github.com/rstudio/DT/issues/359
#' problem statement: cannot access the state of a DT to
#' update only the rows which the user is currently viewing
#' and wrap this function in a module
#' credit: Aaron Berg <aaron@rstudio.com> for debug help
#' THIS EXAMPLE DOES NOT WORK
#' Comments inline
library(shiny)
library(DT)
library(tidyverse)
modUI <- function(id) {
ns <- NS(id)
fluidPage(
fluidRow(
column(2, actionButton(ns('upper'), 'Upper Case')),
column(10, DT::dataTableOutput(ns('foo')))
)
)
}
modServer <- function(input, output, session) {
df <- tibble(letter = letters)
n = nrow(df)
df$ID = seq_len(n)
loopData = reactive({
input$upper
#' Looping update of ID columne works,
#' but is not filtering on what the user views
df$ID <<- c(df$ID[n], df$ID[-n])
#' however the state is NULL
print(isolate(input$foo_state$start))
print(isolate(input$foo_state$length))
if(is.null(isolate(input$foo_state$length))){
start <- 0
end <- 0
} else{
start <- (isolate(input$foo_state$start) + 1)
end <- isolate(input$foo_state$start + ifelse(is.null(input$foo_state$length), 1, input$foo_state$length))
}
df$letter[start:end] <<- toupper(df$letter[start:end])
df
})
output$foo = DT::renderDataTable(isolate(loopData()))
proxy = dataTableProxy('foo')
observe({
replaceData(proxy, loopData(), resetPaging = FALSE)
})
}
shinyApp(
ui = modUI('module'),
server = function(input, output, session) callModule(modServer, 'module')
)