简体   繁体   中英

How to update textOutput in R Shiny within the execution of an actionButton?

I am building an R Shiny UI (split as UI and Server) which spends about three hours building a data.frame of disease clinical records given some Shiny UI parameters. On completion, the data.frame is passed to a Cox model and the result will be displayed as a plot.

When running R on the terminal the code will print information during those three hours eg, how many patients/drugs it has parsed.

I have tried using separate textOutput UI features but I can't seem to get the textOutput to update from within a function call executed on the event of clicking a button. I believe this could be scope related. My code is split by UI and Server:

Note: the button is clicked once and I would like to see the textOutput to be updated several times on that click given a call from within a loop.

library(shiny)


shinyUI(fluidPage(

  # Application title
  titlePanel("CPRD EHR Statistical Toolset"),


  sidebarLayout(
    sidebarPanel(
      helpText("A long list of Input features below here."),
      mainPanel(
        h4("Medical record construction"),
        textOutput("numPatientsOutput"),
        actionButton("executeButton", "Execute Cox")
      )
    )
  )
))

library(shiny)

shinyServer(function(input, output) {

  observeEvent(input$executeButton, {
    coxDF<-runBuildModel(input, output)
  }) #endf of execute action

})

runBuildModel <- function(input, output) {
  for(i in 1:10) {
    #This is not updating.
    output$numPatientsOutput <- renderText({paste("patient:",i)})
  }
}

The server basically runs all the code before rendering it. That's why you only get your last line of text.

What you can do is create a reactiveValue and update this value in the for loop. In addition, you have to create an observer to keep track of the value.

Working example

library(shiny)

ui <- shinyUI(fluidPage(

  # Application title
  titlePanel("CPRD EHR Statistical Toolset"),


  sidebarLayout(
    sidebarPanel(
      helpText("A long list of Input features below here.")),
    mainPanel(
      h4("Medical record construction"),
      htmlOutput("numPatientsOutput"),
      actionButton("executeButton", "Execute Cox")
    )

  )
))

server <- shinyServer(function(input, output) {
  runBuildModel <- function(input, output) {
    for(i in 1:10) {
      #This is not updating.
      rv$outputText = paste0(rv$outputText,"patient:",i,'<br>')
    }
  }

  rv <- reactiveValues(outputText = '')

  observeEvent(input$executeButton, {
    coxDF<-runBuildModel(input, output)
  }) #endf of execute action

  observe(output$numPatientsOutput <- renderText(HTML(rv$outputText)))
})



shinyApp(ui, server)

I realize that this is resurrecting and VERY old question, but I've faced the same problem myself and found a way to solve it. I wanted to provide an answer here for others that might find this page.

library(shiny)
library(shinyjs)

ui <- shinyUI(fluidPage(
  
  # Application title
  titlePanel("CPRD EHR Statistical Toolset"),
  
  sidebarLayout(
    sidebarPanel(
      helpText("A long list of Input features below here.")),
    mainPanel(
      useShinyjs(),
      h4("Medical record construction"),
      htmlOutput("numPatientsOutput"),
      actionButton("executeButton", "Execute Cox")
    )
  )
))

server <- shinyServer(function(input, output) {
  runBuildModel <- function(input, output) {
    for(i in 1:10) {
      #This is not updating.
      Sys.sleep(1)
      rv$outputText = paste0(rv$outputText,"patient:",i,'<br>')
      shinyjs::html(id = 'numPatientsOutput', rv$outputText)
    }
  }
  
  rv <- reactiveValues(outputText = '')
  
  observeEvent(input$executeButton, {
    coxDF<-runBuildModel(input, output)
  }) #endf of execute action
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM