问题描述
我将数据框作为输入并在其中添加一些额外的列。然后,我使用for循环对每一行进行处理。该处理需要时间,因此我想将处理后的行显示为单独的ui元素。
例如, 如果正在处理第一行,
ROW-1
如果正在处理第二行,那么它将在下一行ROW-1中添加
ROW-1
ROW-2
随着我的for循环遍历行,最新处理的行将作为UI元素添加到列表中。
我用过lapply,但是它会处理所有行,然后一起显示所有内容。
library(shiny)
ui <- fluidPage(
uIoUtput("ui1")
)
server <- function(input,output) {
Init_vals <- 1:5
for(i in 1:5){
Sys.sleep(5)
output[[paste("ui",i,sep="")]] = renderUI({
list(
fluidPage(
fluidRow(
textInput(
inputId=paste0("id",i),label = "here",value = Init_vals[i]
)
)
),uIoUtput(paste("ui",i + 1,sep=""))
)
})
}
}
shinyApp(ui = ui,server = server)
在这里,您可以看到仅生成了最后一个ui元素,并且跳过了ui1到ui4的其他元素!每隔5秒,应用应会产生新的文本输入。
解决方法
就像吉姆建议的那样,请尝试使用lapply
而不是for
循环:
server <- function(input,output) {
lapply(1:5,function(i) {
Sys.sleep(5)
output[[paste0("ui",i)]] <- renderUI({
list(
fluidPage(
fluidRow(
textInput(
inputId = paste0("id",i),label = "here",value = i
)
)
),uiOutput(paste0("ui",i + 1))
)
})
})
}
好像闪亮有一些独特之处,可以防止为输出正确分配for
循环。您也可以使用purrr::walk()
编辑:
您是正确的,shiny
等待显示所有内容,直到server
函数完成运行为止。我相信shiny
就是这样设计的-动态UI元素(用renderUI
创建)将不显示,直到它们完成所有正在创建。
如果您的目标是告知用户该过程可能需要多长时间,则可能要改用withProgress()
:
server <- function(input,output) {
withProgress(
message = 'Calculation in progress',detail = 'This may take a while...',value = 0,expr = {
lapply(1:5,i)]] <- renderUI({
list(
fluidPage(
fluidRow(
textInput(
inputId = paste0("id",value = i
)
)
),i + 1))
)
})
incProgress(1 / 5)
})
})
}