R Shiny:在动态情况下有条件地更新可能的用户输入选择
R Shiny: conditional update of possible user input choices in a dynamic situation
我创建了一个微型 Shiny 应用程序,其中询问用户 s/he 想要切割给定的日期向量(2 到 4 之间)的周期数。然后,对于用户想要的每个时间段(最后一个除外)s/he 被要求 select 该时间段的最后日期。
该应用程序正在运行,但是,我担心某些愚蠢的用户可能 select 不是增量的结束日期,例如,select 时间段 1 的结束日期可能会晚些时候时间比结束日期selected for Time Period 2, etc.
换句话说,我希望在将 cutpoint2 定义为仅包含 cutpoint1 日期之后的日期等时为用户提供选择(日期)。因此,如果用户 selected ' 2006-12-31' 作为时间段 1 的结束日期,我希望时间段 2 的用户输入框可用的日期在该日期之后开始。
但是,我不确定在这种超级动态的情况下是否可行,因为首先,我第一次创建了这些切点输入 - 当用户根本没有被问及日期时,所以我可以让他们真正地相互依赖。然后我要求用户定义切点 - 然后我希望该动态开始。
感谢您的建议!
library(shiny)
ui = shinyUI(fluidPage(
titlePanel("Defining time periods"),
sidebarLayout(
sidebarPanel(
numericInput("num_periodsnr", label = "Desired number of time periods?",
min = 2, max = 4, value = 2),
uiOutput("period_cutpoints"),
actionButton("submit", "Update time periods")
),
mainPanel( # Just shows what was selected
textOutput("nr_of_periods"),
textOutput("end_dates")
)
)
))
server = shinyServer(function(input, output, session) {
library(lubridate)
output$nr_of_periods <- renderPrint(input$num_periodsnr)
# Dates string to select dates from:
dates <- seq(ymd('2016-01-02'), ymd('2017-12-31'), by = '1 week')
output$period_cutpoints <- renderUI({
req(input$num_periodsnr)
lapply(1:(input$num_periodsnr - 1), function(i) {
selectInput(inputId = paste0("cutpoint", i),
label = paste0("Select the last date of Time Period ", i, ":"),
choices = dates)
})
})
dates_chosen <- reactiveValues(x = NULL)
observeEvent(input$submit, {
dates_chosen$x <- list()
lapply(1:(input$num_periodsnr - 1), function(i) {
dates_chosen$x[[i]] <- input[[paste0("cutpoint", i)]]
})
})
output$end_dates <- renderText({paste(as.character(dates_chosen$x), collapse = ", ")})
})
shinyApp(ui = ui, server = server)
将此插入到您的服务器函数中:
observe({
if(input$num_periodsnr > 2){
for(i in 2:(input$num_periodsnr - 1)) {
updateSelectInput(session, paste0("cutpoint", i), choices = dates[dates > input[[paste0("cutpoint", i-1)]]])
}
}
})
由于您的 lapply 每当您增加周期数时您都会创建新的 selectInput ,您(无意中)覆盖以前的结果并重置开始周期,每当用户从例如3 到 4 个切点周期。
我创建了一个微型 Shiny 应用程序,其中询问用户 s/he 想要切割给定的日期向量(2 到 4 之间)的周期数。然后,对于用户想要的每个时间段(最后一个除外)s/he 被要求 select 该时间段的最后日期。
该应用程序正在运行,但是,我担心某些愚蠢的用户可能 select 不是增量的结束日期,例如,select 时间段 1 的结束日期可能会晚些时候时间比结束日期selected for Time Period 2, etc.
换句话说,我希望在将 cutpoint2 定义为仅包含 cutpoint1 日期之后的日期等时为用户提供选择(日期)。因此,如果用户 selected ' 2006-12-31' 作为时间段 1 的结束日期,我希望时间段 2 的用户输入框可用的日期在该日期之后开始。
但是,我不确定在这种超级动态的情况下是否可行,因为首先,我第一次创建了这些切点输入 - 当用户根本没有被问及日期时,所以我可以让他们真正地相互依赖。然后我要求用户定义切点 - 然后我希望该动态开始。
感谢您的建议!
library(shiny)
ui = shinyUI(fluidPage(
titlePanel("Defining time periods"),
sidebarLayout(
sidebarPanel(
numericInput("num_periodsnr", label = "Desired number of time periods?",
min = 2, max = 4, value = 2),
uiOutput("period_cutpoints"),
actionButton("submit", "Update time periods")
),
mainPanel( # Just shows what was selected
textOutput("nr_of_periods"),
textOutput("end_dates")
)
)
))
server = shinyServer(function(input, output, session) {
library(lubridate)
output$nr_of_periods <- renderPrint(input$num_periodsnr)
# Dates string to select dates from:
dates <- seq(ymd('2016-01-02'), ymd('2017-12-31'), by = '1 week')
output$period_cutpoints <- renderUI({
req(input$num_periodsnr)
lapply(1:(input$num_periodsnr - 1), function(i) {
selectInput(inputId = paste0("cutpoint", i),
label = paste0("Select the last date of Time Period ", i, ":"),
choices = dates)
})
})
dates_chosen <- reactiveValues(x = NULL)
observeEvent(input$submit, {
dates_chosen$x <- list()
lapply(1:(input$num_periodsnr - 1), function(i) {
dates_chosen$x[[i]] <- input[[paste0("cutpoint", i)]]
})
})
output$end_dates <- renderText({paste(as.character(dates_chosen$x), collapse = ", ")})
})
shinyApp(ui = ui, server = server)
将此插入到您的服务器函数中:
observe({
if(input$num_periodsnr > 2){
for(i in 2:(input$num_periodsnr - 1)) {
updateSelectInput(session, paste0("cutpoint", i), choices = dates[dates > input[[paste0("cutpoint", i-1)]]])
}
}
})
由于您的 lapply 每当您增加周期数时您都会创建新的 selectInput ,您(无意中)覆盖以前的结果并重置开始周期,每当用户从例如3 到 4 个切点周期。