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.