Reputation: 363
I have to build a simple web app using Shiny where I need to make a plot at each iteration of a sequential computation. Using this post I could manage to do it.
Now what I want is to be able to stop the looping process with a click. The action button should work like a pause/play button but I could not make it work as expected.
When going through the code I can't understand why the observe would run when pause_value()
is true. I added some print
to see what is actually done and when. Here is the code:
library(shiny)
server <- function(input, output, session) {
rv <- reactiveValues(i = 0)
maxIter <- 10
output$myplot <- renderPlot( {
if(rv$i > 0) {
x <- seq_len(rv$i * 100)
y <- (x + 1)^2 - 1 # this will do for now
plot(x, y, main = sprintf("Round %i", rv$i), type = "l")
} else {
plot(1:1, main = "Placeholder")
}
})
pause_value <- reactive({
if (input$run %% 2 == 0) {
TRUE
} else {
FALSE
}
}
)
observeEvent(
eventExpr = pause_value(),
handlerExpr = {
if (pause_value()) {
updateActionButton(
session,
inputId = "run",
label = "RUN"
)
} else {
updateActionButton(
session,
inputId = "run",
label = "STOP"
)
}
}
)
observeEvent(
eventExpr = {
input$run
pause_value()
},
ignoreNULL = FALSE,
ignoreInit = TRUE,
handlerExpr = {
print(pause_value())
if (!pause_value()) {
rv$i <- 0
observe({
print("-----")
isolate({
rv$i <- rv$i + 1
})
if (isolate(rv$i) < maxIter){
invalidateLater(2000, session)
}
})
} else {
print("=====")
}
})
}
ui <- fluidPage(
actionButton("run", "RUN"),
plotOutput("myplot")
)
shinyApp(ui = ui, server = server)
I have been trying to make my app works for 2 days now. And even on this simple example I can't figure out the problem.
I hope someone can help.
My session info :
R version 3.5.0 (2018-04-23)
Platform: x86_64-apple-darwin15.6.0 (64-bit)
Running under: macOS 10.14.1
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/3.5/Resources/lib/libRlapack.dylib
locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] shiny_1.2.0
loaded via a namespace (and not attached):
[1] compiler_3.5.0 magrittr_1.5 R6_2.3.0 promises_1.0.1 later_0.7.5
[6] htmltools_0.3.6 tools_3.5.0 Rcpp_0.12.19 jsonlite_1.5 digest_0.6.18
[11] xtable_1.8-3 httpuv_1.4.5 mime_0.6 packrat_0.4.9-2 rlang_0.3.0.1
Cheers
Upvotes: 0
Views: 259
Reputation: 711
Consider the following approach, using a timer()
that controls the value of a rv$go
variable (which in turn controls whether the rv$i
will increment or not:
library(shiny)
server <- function(input, output, session) {
rv <- reactiveValues(i = 0, go = F)
maxIter <- 10
timer <- reactiveTimer(2000)
output$myplot <- renderPlot({
if(rv$i > 0) {
x <- seq_len(rv$i * 100)
y <- (x + 1)^2 - 1 # this will do for now
plot(x, y, main = sprintf("Round %i", rv$i), type = "l")
} else {
plot(1:1, main = "Placeholder")
}
})
observeEvent(input$run, {
rv$go <- !rv$go
updateActionButton(
session,
inputId = "run",
label = "STOP"
)
})
observeEvent(timer(), {
req(rv$i < maxIter)
req(rv$go)
rv$i <- rv$i + 1
})
}
ui <- fluidPage(
actionButton("run", "RUN"),
plotOutput("myplot")
)
shinyApp(ui = ui, server = server)
Upvotes: 1