我正在编写一个闪亮的应用程序,它会在按下按钮时生成一些绘图。当用户按下按钮时计算开始,我想在按下按钮后更新按钮的标签以显示当前正在进行计算。计算完成后,应恢复到“默认”状态。我认为这很容易用
updateActionButton
做到,但不知何故我无法让它工作。这是一个可重现的小例子。
if (interactive()) {
ui <- fluidPage(
actionButton("update", "Do calculation"),
)
server <- function(input, output, session) {
observeEvent(input$update, {
# Change the button label
updateActionButton(session, "update", label = "Running calculation")
# This is a random calculation which takes a few seconds as a placeholder.
result <- 0
for (i in 1:5000000) {
result <- result + sqrt(i)
}
updateActionButton(session, "update", label = "finished calculation")
})
}
shinyApp(ui, server)
}
看起来它只是跳过了第一个
updateActionButton
调用......
非常感谢任何对我做错的事情的见解!
干杯!
来自
?updateActionButton
:
输入更新器函数向客户端发送一条消息,告诉它更改输入对象的设置。 所有观察者(包括输出)运行完毕后,消息被收集并发送。
这意味着当您单击按钮时,只有在
for
循环完成后才会发送更新。
由于您尝试两次更新按钮的标签,因此仅将最后一次更新发送到客户端。
有多种解决方案,我将重点介绍两个最简单的解决方案:
设置按钮的
onclick
属性。
这样,您就可以避免需要与服务器进行通信来更新 UI。服务器需要做的就是在计算完成后提醒客户端。
library(shiny)
ui <- fluidPage(
actionButton(
"update",
"Do calculation",
onclick = "$('#update').html('running...')"
),
)
server <- function(input, output, session) {
observeEvent(input$update, {
# This is a random calculation which takes a few seconds as a placeholder.
result <- 0
for (i in 1:5000000) {
result <- result + sqrt(i)
}
updateActionButton(session, "update", label = "finished calculation")
})
}
shinyApp(ui, server)
使用
{shinyFeedback}
。
这样,您就可以避免像上面的解决方案 1 中那样编写临时内联 js。您还会在按钮上看到一个漂亮的旋转器。
library(shiny)
library(shinyFeedback)
ui <- fluidPage(
useShinyFeedback(),
loadingButton(
inputId = "update",
label = "Do calculation",
loadingLabel = "running..."
),
)
server <- function(input, output, session) {
observeEvent(input$update, {
# This is a random calculation which takes a few seconds as a placeholder.
result <- 0
for (i in 1:5000000) {
result <- result + sqrt(i)
}
resetLoadingButton(inputId = "update")
})
}
shinyApp(ui, server)
在 Mwavu 的帮助下,我成功地完成了我正在尝试的事情。虽然说实话,我不太明白它为什么有效,如果有人能向我解释它为什么有效,我将不胜感激。
library(shiny)
ui <- fluidPage(
loadingButton("renderButton", "Render Plot"),
plotOutput("myPlot"),
textOutput("renderStatus") #if i remove this, the code doesnt work
)
server <- function(input, output, session) {
rendered <- reactiveVal(FALSE)
observeEvent(input$renderButton, {
rendered(FALSE) # Reset the rendered status
output$myPlot <- renderPlot({
# Your plotting code here
plot(runif(100000), runif(100000), main = "New Plot") # random plot which takes a few seconds to render
rendered(TRUE) # Mark the plot as rendered
})
})
output$renderStatus <- reactive({ # <- if I remove the output$renderStatus the code doesnt work anymore (it is stuck in the "loading" annimation)
if (rendered()) {
resetLoadingButton(inputId = "renderButton")
}
})
}
shinyApp(ui, server)
具体来说,我不明白为什么有必要包括
textOutput("renderStatus")
和output$renderStatus
。我认为有这个代码块就足够了
reactive({
if (rendered()) {
resetLoadingButton(inputId = "renderButton")
}
})
触发按钮的默认状态。