如果输入已更改,则启用操作按钮
Enable Action Button if Input has changed
我的应用程序应遵循以下逻辑:如果按下操作按钮,将禁用所有输入并执行长时间计算。当计算完成并绘制其结果时,除操作按钮外的所有输入都将再次启用。如果用户决定更改一个输入,则操作按钮将启用。
除了最后一点,操作按钮的启用之外,大部分所需的行为都有效。这是我的服务器函数(操作按钮名为“go”):
server <- function(input, output, session) {
allinputIds <- reactive(names(input))
shiny::observeEvent(input$go, {
for (id in allinputIds()) shinyjs::disable(id)
})
# ==> here is some trouble: not working
shiny::observeEvent(allinputIds(), shinyjs::enable("go"))
# from here starts the real work
bins <- shiny::eventReactive(input$go, {
x <- faithful$waiting
Sys.sleep(1.5)
seq(min(x), max(x), length.out = input$bins + 1)
})
output$figure <- shiny::renderPlot({
x <- faithful$waiting
hist(
x, breaks = bins(), col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times"
)
for (id in setdiff(allinputIds(), "go")) shinyjs::enable(id)
})
}
我如何才能观察到任何输入已更改?在标记为“==>”的行之后没有 allinputIds()
,我尝试了 input
,但这都不起作用。
作为第二个问题,您会推荐什么来封装这个按钮/禁用/启用模式,我计划在多个闪亮模块上使用它。如果我能专注于主要代码,即 bins
和 output$figure <- ...
.
就好了
感谢任何提示!
为了可重复性,这里是 ui 函数:
ui <- shiny::tagList(
shinyjs::useShinyjs(),
shiny::navbarPage(title="Test 2",
tabPanel(title="Old Faithful",
shiny::sidebarLayout(
shiny::sidebarPanel(
shiny::sliderInput(
inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
shiny::mainPanel(
shiny::actionButton("go", "Update"),
shinycssloaders::withSpinner(plotOutput(outputId="figure")),
shiny::h4(shiny::textOutput("msg"))
)
)
)
)
)
shiny::shinyApp(ui, server)
问题在于,在 shiny::observeEvent(allinputIds(), shinyjs::enable("go"))
中,您只需检查输入 ID 的 names/amount 是否发生变化 - 它们不会。您实际上需要检查任何输入(除了操作按钮)的值是否已更改。因此,您可以像 c(input$bins, input$...)
一样将所有输入直接放入观察中,或者进行额外的反应来检查值并称之为反应。
library(shiny)
server <- function(input, output, session) {
allinputIds <- reactive(names(input))
changingInputValues <- reactive({
checkIds <- setdiff(names(input), "go")
lapply(checkIds, function(x) input[[x]])
})
observeEvent(input$go, {
lapply(allinputIds(), shinyjs::disable)
})
# ==> here is some trouble: not working
observeEvent(changingInputValues(), shinyjs::enable("go"))
# from here starts the real work
bins <- eventReactive(input$go, {
x <- faithful$waiting
Sys.sleep(1.5)
seq(min(x), max(x), length.out = input$bins + 1)
})
output$figure <- renderPlot({
x <- faithful$waiting
hist(
x, breaks = bins(), col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times"
)
lapply(setdiff(allinputIds(), "go"), shinyjs::enable)
})
}
ui <- tagList(
shinyjs::useShinyjs(),
navbarPage(title="Test 2",
tabPanel(title="Old Faithful",
sidebarLayout(
sidebarPanel(
sliderInput(
inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
mainPanel(
actionButton("go", "Update"),
shinycssloaders::withSpinner(plotOutput(outputId="figure")),
h4(textOutput("msg"))
)
)
)
)
)
shinyApp(ui, server)
请注意,我已将 for
循环更改为 lapply
,因为 for
循环往往不能很好地与 shiny 配合使用(不幸的是,我不确定为什么)。有几次在使用循环时启用输入不起作用,但使用 lapply
我没有遇到任何问题。
我的应用程序应遵循以下逻辑:如果按下操作按钮,将禁用所有输入并执行长时间计算。当计算完成并绘制其结果时,除操作按钮外的所有输入都将再次启用。如果用户决定更改一个输入,则操作按钮将启用。
除了最后一点,操作按钮的启用之外,大部分所需的行为都有效。这是我的服务器函数(操作按钮名为“go”):
server <- function(input, output, session) {
allinputIds <- reactive(names(input))
shiny::observeEvent(input$go, {
for (id in allinputIds()) shinyjs::disable(id)
})
# ==> here is some trouble: not working
shiny::observeEvent(allinputIds(), shinyjs::enable("go"))
# from here starts the real work
bins <- shiny::eventReactive(input$go, {
x <- faithful$waiting
Sys.sleep(1.5)
seq(min(x), max(x), length.out = input$bins + 1)
})
output$figure <- shiny::renderPlot({
x <- faithful$waiting
hist(
x, breaks = bins(), col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times"
)
for (id in setdiff(allinputIds(), "go")) shinyjs::enable(id)
})
}
我如何才能观察到任何输入已更改?在标记为“==>”的行之后没有 allinputIds()
,我尝试了 input
,但这都不起作用。
作为第二个问题,您会推荐什么来封装这个按钮/禁用/启用模式,我计划在多个闪亮模块上使用它。如果我能专注于主要代码,即 bins
和 output$figure <- ...
.
感谢任何提示!
为了可重复性,这里是 ui 函数:
ui <- shiny::tagList(
shinyjs::useShinyjs(),
shiny::navbarPage(title="Test 2",
tabPanel(title="Old Faithful",
shiny::sidebarLayout(
shiny::sidebarPanel(
shiny::sliderInput(
inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
shiny::mainPanel(
shiny::actionButton("go", "Update"),
shinycssloaders::withSpinner(plotOutput(outputId="figure")),
shiny::h4(shiny::textOutput("msg"))
)
)
)
)
)
shiny::shinyApp(ui, server)
问题在于,在 shiny::observeEvent(allinputIds(), shinyjs::enable("go"))
中,您只需检查输入 ID 的 names/amount 是否发生变化 - 它们不会。您实际上需要检查任何输入(除了操作按钮)的值是否已更改。因此,您可以像 c(input$bins, input$...)
一样将所有输入直接放入观察中,或者进行额外的反应来检查值并称之为反应。
library(shiny)
server <- function(input, output, session) {
allinputIds <- reactive(names(input))
changingInputValues <- reactive({
checkIds <- setdiff(names(input), "go")
lapply(checkIds, function(x) input[[x]])
})
observeEvent(input$go, {
lapply(allinputIds(), shinyjs::disable)
})
# ==> here is some trouble: not working
observeEvent(changingInputValues(), shinyjs::enable("go"))
# from here starts the real work
bins <- eventReactive(input$go, {
x <- faithful$waiting
Sys.sleep(1.5)
seq(min(x), max(x), length.out = input$bins + 1)
})
output$figure <- renderPlot({
x <- faithful$waiting
hist(
x, breaks = bins(), col = "#75AADB", border = "white",
xlab = "Waiting time to next eruption (in mins)",
main = "Histogram of waiting times"
)
lapply(setdiff(allinputIds(), "go"), shinyjs::enable)
})
}
ui <- tagList(
shinyjs::useShinyjs(),
navbarPage(title="Test 2",
tabPanel(title="Old Faithful",
sidebarLayout(
sidebarPanel(
sliderInput(
inputId = "bins",
label = "Number of bins:",
min = 1,
max = 50,
value = 30
)
),
mainPanel(
actionButton("go", "Update"),
shinycssloaders::withSpinner(plotOutput(outputId="figure")),
h4(textOutput("msg"))
)
)
)
)
)
shinyApp(ui, server)
请注意,我已将 for
循环更改为 lapply
,因为 for
循环往往不能很好地与 shiny 配合使用(不幸的是,我不确定为什么)。有几次在使用循环时启用输入不起作用,但使用 lapply
我没有遇到任何问题。