3
votes

R shiny: mettez à jour tabsetpanel avant de terminer tout le code observeEvent

Je souhaite mettre à jour le tabsetpanel immédiatement et ne pas attendre la fin de la fonction de téléchargement. ici vous pouvez trouver un code simple Il a un bouton, et quand il est pressé, il simule un téléchargement et met à jour un tabsetpanel. Je souhaite mettre à jour le panneau avant de terminer le téléchargement.

Merci!

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)


1 commentaires

Essayez d'utiliser updateTabsetPanel dans son propre observeEvent , avant observeEvent pour le téléchargement.


3 Réponses :


0
votes

Pas vraiment une réponse, je sais, mais je ne comprends pas vraiment pourquoi ce qui suit ne fonctionne pas. Il garantit le bon ordre d'exécution, mais le problème persiste. Je suppose que le problème est que les mises à jour ne sont pas vidées avant la fin des deux.

> shinyApp(ui = ui, server = server)

Listening on http://127.0.0.1:6800
A EXECUTED
B EXECUTED

En exécutant cette application et en appuyant sur le bouton, j'obtiens:

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)

Pourtant, l'ensemble d'onglets est mis à jour après le rendu du tracé. Quelqu'un peut peut-être faire la lumière sur ce qui se passe ici.


1 commentaires

Shiny ne met à jour l'interface utilisateur qu'après que toutes les instructions d'observation ou réactives invalides ont été mises à jour. Par conséquent, vous devez créer des chaînes réactives lorsque vous souhaitez un flux de travail comme celui-ci



1
votes

Shiny ne met à jour l'interface utilisateur qu'après la mise à jour de toutes les instructions d'observation ou réactives invalides. Par conséquent, vous devez créer des chaînes réactives lorsque vous souhaitez un flux de travail comme celui-ci. J'ai résolu cela en extrayant la préparation des données dans une déclaration réactive séparée (ce n'est pas vraiment nécessaire mais toujours une bonne idée), puis j'ai déplacé l'intrigue dans l'onglet de résumé. J'ai supposé que la raison de changer d'onglet était de voir l'intrigue. Veuillez me corriger si ce n'est pas correct. Mais cela reporte les calculs jusqu'à ce que l'onglet s'affiche. Maintenant, pour éviter que les calculs ne commencent avant que le bouton goPlot ne soit cliqué, je viens d'ajouter la ligne

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)

au début de l'instruction réactive.

XXX

J'espère que cela vous aidera !!


1 commentaires

Merci une excellente solution!



1
votes

Vous pouvez faire:

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)

Ou exécuter du code Javascript pour changer l'onglet actif, par exemple avec shinyjs:

  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
    ......


0 commentaires