编辑:使用updateQueryString 更新网址位置栏的功能找到了代理解决方案。基本上我所做的就是在 ui 中添加一个 selectInput,显示之前保存的所有书签,让用户选择一个来恢复。
使用 rds 文件实现还原有一些限制。第一个是 input.rds(书签创建的文件)只显示输入的名称和值而不是类型,所以无法判断值是否对应于actionButton 或textInput。即使我们实现了一个识别每种类型的系统,像updateActionButton 这样的一些函数也没有value 参数,所以它的值几乎永远不会是正确的。
library(shiny)
library(tidyverse)
get_last_bookmark <- function(){
list.files(path = 'shiny_bookmarks/') %>% #path to every folder containing bookmarked data.
map_df(., ~paste0('shiny_bookmarks/', .x) %>%
file.info ) %>%
slice_max(atime) %>%
rownames()
}
get_last_bookmark <- possibly(get_last_bookmark, otherwise = '') #avoid empty folder error
ui <- function(request){fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("data", "Choose CSV File", accept = ".csv"),
checkboxInput("header", "Header", TRUE),
fileInput("file1", "Choose RDA File", accept = ".rda"),
bookmarkButton(),
verbatimTextOutput('last_dir'),
br(),
selectInput('select_state', 'Select Bookmark Folder To Restore', choices = list.files(path = 'shiny_bookmarks/'),selected = get_last_bookmark() %>% str_sub(17, -1)),
actionButton('dorestore', 'Restore it!')
),
mainPanel(
tableOutput("data_head"),
tableOutput("contents"),
selectInput("select", "Select Variable", choices = NULL, selected = NULL),
plotOutput("boxplot")
)
)
)
}
server <- function(input, output, session) {
output$last_dir <- renderText({
paste0('The last bookmark is stored in: ', get_last_bookmark())
})
onBookmark(function(state){
output$last_dir <- renderText({
paste0('The last bookmark is stored in: ', get_last_bookmark())
})
updateSelectInput(session = session, 'select_state', choices = list.files(path = 'shiny_bookmarks/'), selected = get_last_bookmark() %>% str_sub(17, -1) )
state$values$input_value_to_restore <- input$select
})
onBookmarked(function(state){
#avoid showing message window
})
observeEvent(input$dorestore, {
updateQueryString(queryString = paste0('?_state_id_=', input$select_state), session = session)
session$reload()
})
dataset <- reactive({
file <- input$data
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "csv", "Please upload a csv file"))
my_data <- read.csv(file$datapath, header = input$header)
my_data
})
output$data_head <- renderTable({
head(dataset())
})
output$boxplot <- renderPlot({
req(dataset())
req(input$select)
boxplot(dataset()[[input$select]], horizontal = TRUE)
})
observeEvent(input$data, { #this will cause input$select to reset when the app restores because of the way shiny restores the app.
req(dataset())
updateSelectInput(session = getDefaultReactiveDomain(), "select", label = "Select Variable", choices = c("", names(dataset())))
})
#avoid the dynamic parts of the app to reset
onRestored(function(state) {
updateSelectInput(session, 'select', selected = state$values$input_value_to_restore)
})
output$out <- renderText({
if (input$caps)
toupper(input$txt)
else
input$txt
})
output$contents <- renderTable({
file <- input$file1
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "rds", "Please upload a RDA file"))
readRDS(file$datapath)
})
}
shinyApp(ui, server, enableBookmarking = "server")
此应用程序将读取最后创建的带有书签数据的文件夹,并
在名为“Rds From Last State”的选项卡中打印其内容
library(shiny)
library(tidyverse)
ui <- function(request){fluidPage(
sidebarLayout(
sidebarPanel(
fileInput("data", "Choose CSV File", accept = ".csv"),
checkboxInput("header", "Header", TRUE),
fileInput("file1", "Choose RDS File", accept = ".rds"),
bookmarkButton()
),
mainPanel(
tabsetPanel(
tabPanel('Tables',
tableOutput("data_head"),
tableOutput("contents"),
selectInput("select", "Select Variable", choices = NULL, selected = NULL),
plotOutput("boxplot")),
tabPanel('Rds From Last State',
verbatimTextOutput('bookmark_rds'))
)
)
)
)
}
server <- function(input, output) {
dataset <- reactive({
file <- input$data
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "csv", "Please upload a csv file"))
my_data <- read.csv(file$datapath, header = input$header)
my_data
})
output$data_head <- renderTable({
head(dataset())
})
output$boxplot <- renderPlot({
req(dataset())
boxplot(dataset(), main = input$select, horizontal = TRUE)
})
observeEvent(input$data, {
req(dataset())
updateSelectInput(session = getDefaultReactiveDomain(), "select", label = "Select Variable", choices = c("", names(dataset())))
})
output$out <- renderText({
if (input$caps)
toupper(input$txt)
else
input$txt
})
output$contents <- renderTable({
file <- input$file1
ext <- tools::file_ext(file$datapath)
req(file)
validate(need(ext == "rds", "Please upload a RDS file"))
readRDS(file$datapath)
})
rds_directory <- reactiveValues()
onRestore(function(state) {
#The last modified folder inside the bookmarks directory will contain the latest values to restore.
last_bookmark_dir <-
list.files(path = 'shiny_bookmarks/') %>% #path to every folder containing bookmarked data.
map_df(., ~paste0('shiny_bookmarks/', .x) %>%
file.info ) %>%
slice_max(atime) %>% rownames()
print(paste('Last bookmark dir:', last_bookmark_dir))
print(list.files(last_bookmark_dir))
rds_directory$rds <- last_bookmark_dir %>%
list.files %>%
str_subset('\\.rds') %>% #subset all the .rds files
{paste0(last_bookmark_dir, '/', .)} %>% map(~ readRDS(.x))
print(rds_directory$rds)
})
output$bookmark_rds <- renderPrint({
req(rds_directory$rds) #If there's no bookmark this chunk won't execute
map(rds_directory$rds, ~ .x)
})
}
shinyApp(ui, server, enableBookmarking = "server")