以下应用程序具有两个输入,而第二个输入依赖于第一个输入并在服务器站点上更新。如何实现书签,使第二个变量(Input2)在使用链接恢复站点时仅更新一次?
df <- structure(list(Input1 = c("A", "A", "A", "A", "A", "B", "B",
"B", "B", "B", "C", "C", "C", "C", "C"), Input2 = c(1L, 2L, 3L,
5L, 7L, 2L, 4L, 6L, 7L, 8L, 1L, 4L, 5L, 6L, 7L)), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
Input1 = c("A", "B", "C"), .rows = structure(list(1:5, 6:10, 11:15), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, -3L), .drop = TRUE, class = c("tbl_df", "tbl", "data.frame")))
shinyApp(
ui = function(request) {fluidPage(
selectInput("input1", "input1", choices = unique(df$Input1)),
selectInput("input2", "input2", choices = NA)
)},
server = function(input, output, session){
observe({
req(input$input1)
tmp_input2 <- df %>%
filter(Input1 == input$input1) %>%
pull(Input2)
updateSelectInput(session, "input2", choices = tmp_input2)
})
observe({
session$doBookmark()
})
onBookmarked(function(url) {
updateQueryString(url)
})
onRestored(function(state) {
updateSelectInput(session, "input2", selected = state$input$input2)
})
observe({
print(input$input2)
})
},enableBookmarking = "url")
使用例如恢复网站时此链接http://127.0.0.1:6279/?_inputs_&input1=%22A%22&input2=%225%22
然后你可以在控制台中观察到首先是观察者被触发,而不是onRestore。这在这个应用程序中没有问题,但是我的在这里触发了一个需要一些时间的事件,并且由于它被触发两次(观察者,而不是 onRestored),因此用户体验减少了两倍。
我尝试使用逻辑向量(
restored
),该向量在 onRestored 函数中设置为 TRUE,但没有成功。
在恢复时在观察者内部设置 req(restored) 是有效的,但当网站空白启动时当然会失败。
onRestore
,因为它是在所有观察者之前触发的,所以是完美的,但由于需要 Input1
来“计算”Input2
,这是不可能的。
onRestore
就是要走的路。问题是,您无法定义 selected
值,该值不存在于选项中:
library(shiny)
library(dplyr)
DF <- structure(list(Input1 = c("A", "A", "A", "A", "A", "B", "B",
"B", "B", "B", "C", "C", "C", "C", "C"), Input2 = c(1L, 2L, 3L,
5L, 7L, 2L, 4L, 6L, 7L, 8L, 1L, 4L, 5L, 6L, 7L)), class = c("grouped_DF",
"tbl_DF", "tbl", "data.frame"), row.names = c(NA, -15L), groups = structure(list(
Input1 = c("A", "B", "C"), .rows = structure(list(1:5, 6:10, 11:15), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, -3L), .drop = TRUE, class = c("tbl_DF", "tbl", "data.frame")))
shinyApp(
ui = function(request) {
fluidPage(
selectInput("input1", "input1", choices = unique(DF$Input1)),
selectInput("input2", "input2", choices = NA)
)
},
server = function(input, output, session) {
restored_session <- reactiveVal(FALSE)
observe({
if(!restored_session()){
req(input$input1)
tmp_input2 <- DF %>%
filter(Input1 == input$input1) %>%
pull(Input2)
updateSelectInput(session, "input2", choices = tmp_input2)
}
})
# observe({
# session$doBookmark()
# })
onBookmarked(function(url) {
updateQueryString(url)
})
onRestore(function(state) {
restored_session(TRUE)
})
onRestored(function(state) {
updateSelectInput(session, "input2", choices = state$input$input2, selected = state$input$input2)
})
observe({
print(input$input2)
})
},
enableBookmarking = "url"
)