Reputation: 43
I want to update the tabsetpanel immediately, and not wait untill finishing the download function. here you can find a simple code It has a button, and when it presed, it simulate a download, and update a tabsetpanel. I want to update the panel before finishing the download.
Thanks!
server <- function(input, output,session) {
observeEvent(input$goPlot,{
updateTabsetPanel(session, "inTabset",
selected = 'Summary'
)
output$plot <- renderPlot({
input$goPlot # Re-run when button is clicked
# Create 0-row data frame which will be used to store data
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
# Number of times we'll go through the loop
n <- 10
for (i in 1:n) {
# Each time through the loop, add another row of data. This is
# a stand-in for a long-running computation.
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
# Increment the progress bar, and update the detail text.
incProgress(1/n, detail = paste("Doing part", i))
# Pause for 0.1 seconds to simulate a long computation.
Sys.sleep(1)
}
})
plot(dat$x, dat$y)
})
})
}
ui <- shinyUI(fluidPage(
actionButton('goPlot', 'Go plot'),
tabsetPanel(id = "inTabset",
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary")
)
)
)
shinyApp(ui = ui, server = server)
Upvotes: 3
Views: 691
Reputation: 84649
You can do:
observeEvent(input$goPlot, {
updateTabsetPanel(session, "inTabset",
selected = 'Summary'
)
})
output$plot <- renderPlot({
req(input$inTabset == "Summary") # require "Summary" is the active tab
input$goPlot # Re-run when button is clicked
......
Or execute some Javascript code to change the active tab, e.g. with shinyjs
:
library(shiny)
library(shinyjs)
server <- function(input, output,session) {
observeEvent(input$goPlot, {
runjs("$('a[data-value=Summary]').click();") # go to Summary tab
output$plot <- renderPlot({
input$goPlot # Re-run when button is clicked
# Create 0-row data frame which will be used to store data
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
# Number of times we'll go through the loop
n <- 10
for (i in 1:n) {
# Each time through the loop, add another row of data. This is
# a stand-in for a long-running computation.
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
# Increment the progress bar, and update the detail text.
incProgress(1/n, detail = paste("Doing part", i))
# Pause for 0.1 seconds to simulate a long computation.
Sys.sleep(1)
}
})
plot(dat$x, dat$y)
})
})
}
ui <- shinyUI(fluidPage(
useShinyjs(),
actionButton('goPlot', 'Go plot'),
tabsetPanel(id = "inTabset",
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary")
)
))
shinyApp(ui = ui, server = server)
Upvotes: 1
Reputation: 5003
Shiny only updates the UI after all invalidated observe or reactive statements has been updated. Therefore you have to build reactive chains when you want a workflow like this. I solved this though pulling out the data preparation in a separate reactive statement (this is not really necessary but always a good idea) then I moved the plot to the summary tab. I supposed the reason to switch tab was to see the plot. Please correct me if this is not correct. But this postpones the calculations until the tab is shown. Now to prevent that the calculations start before the goPlot
button is clicked I just added the line
req(input$goPlot)
to the beginning of the the reactive statement.
server <- function(input, output,session) {
observeEvent(input$goPlot,{
updateTabsetPanel(session, "inTabset",
selected = 'Summary'
)
generate_plot <- reactive({
req(input$goPlot)
# Create 0-row data frame which will be used to store data
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
# Number of times we'll go through the loop
n <- 10
for (i in 1:n) {
# Each time through the loop, add another row of data. This is
# a stand-in for a long-running computation.
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
# Increment the progress bar, and update the detail text.
incProgress(1/n, detail = paste("Doing part", i))
# Pause for 0.1 seconds to simulate a long computation.
Sys.sleep(1)
}
})
plot(dat$x, dat$y)
})
output$plot <- renderPlot({
generate_plot()
})
})
}
ui <- shinyUI(fluidPage(
actionButton('goPlot', 'Go plot'),
tabsetPanel(id = "inTabset",
tabPanel("Plot"),
tabPanel("Summary", plotOutput("plot"))
)
)
)
shinyApp(ui = ui, server = server)
Hope this helps!!
Upvotes: 2
Reputation: 10253
Not really an answer, I know, but I do not really understand why the following does not work. It ensures the correct execution order, but the problem persists. I guess the problem is the updates are not flushed before both have finished.
server <- function(input, output,session) {
rv <- reactiveValues(goPlot_wait = 0)
observeEvent(input$goPlot,{
cat("A EXECUTED\n")
updateTabsetPanel(session, "inTabset", selected = 'Summary')
rv$goPlot_wait <- rv$goPlot_wait + 1
})
observeEvent(rv$goPlot_wait,{
if(rv$goPlot_wait == 0) {
return()
}
cat("B EXECUTED\n")
output$plot <- renderPlot({
# Create 0-row data frame which will be used to store data
dat <- data.frame(x = numeric(0), y = numeric(0))
withProgress(message = 'Making plot', value = 0, {
# Number of times we'll go through the loop
n <- 10
for (i in 1:n) {
# Each time through the loop, add another row of data. This is
# a stand-in for a long-running computation.
dat <- rbind(dat, data.frame(x = rnorm(1), y = rnorm(1)))
# Increment the progress bar, and update the detail text.
incProgress(1/n, detail = paste("Doing part", i))
# Pause for 0.1 seconds to simulate a long computation.
Sys.sleep(0.25)
}
})
plot(dat$x, dat$y)
})
})
}
ui <- shinyUI(fluidPage(
actionButton('goPlot', 'Go plot'),
tabsetPanel(id = "inTabset",
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary"))))
shinyApp(ui = ui, server = server)
When running this app and pressing the button, I get:
> shinyApp(ui = ui, server = server)
Listening on http://127.0.0.1:6800
A EXECUTED
B EXECUTED
Yet the tabset is updated after the plot has rendered. Perhaps someone can shed some light on what is going on here.
Upvotes: 0