我在我的shiny中生成了一个valueBox
的动态数字,这个数字可以根据用户输入而改变。我设法用renderUI
处理了这个问题,我把想要的数字valueBoxOutput
放在那里,我有一个observe
,它将使用renderValueBox
向他们提供内容。
我的问题是:由于某种原因,renderValueBox
中的代码实际上是在observe
完成之后执行的,因此,由于renderValueBox
处于循环中(以具有动态数量的循环),但在循环之后对所有输出执行代码,所有输出将获得循环的最后值。
下面是一个最小的reprex:
library(shiny)
library(shinydashboard)
library(shinyWidgets)
# Function
compute <- function(id)
{
print(paste("Compute ", id))
return(id)
}
# UI
ui = shinyUI(fluidPage(
titlePanel("Compare"),
useShinydashboard(),
sidebarLayout(
sidebarPanel(
numericInput("numitems", label = "Number of items", min = 1, max = 10, value = 2)
),
mainPanel(
uiOutput("boxes")
)
)
))
# Server
server = shinyServer(function(input, output, session) {
data <- reactiveValues(
ids = list()
)
output$boxes <- renderUI({
print("boxes")
box_list <- list()
id_list <- list()
for(id in 1:(input$numitems)) {
id_box <- paste0("box_", id)
print(paste("boxes - ", id_box))
id_list <- append(id_list, id_box)
box_list <- append(
box_list,
tagList(
shinydashboard::valueBoxOutput(id_box)
)
)
data$ids <- id_list
}
print("boxes end")
fluidRow(box_list)
})
observe({
print("observe")
for(id_box in data$ids) {
print(paste("observe - ", id_box))
output[[id_box]] <- shinydashboard::renderValueBox(valueBox(id_box, compute(id_box), icon = icon("circle-info"), color = "teal"))
}
print("end observe")
})
})
# Run
shinyApp(ui = ui , server = server)
结果如下:
和控制台输出:
如您所见,计算(以及一般的渲染)是在observe函数结束后完成的,两个输出都将使用设置的最后一个id_box(因此是最后一个循环box_2),而不是正确使用box_1和box_2。
我尝试使用force
,在渲染之外计算valueBox,使用React列表,但没有任何效果,因为无论我做什么,渲染都是在观察之后评估的,所以无论如何,只有最后一个循环值才会被使用。
有人知道在循环中强制执行的方法吗?或者看到另一种实现相同结果的方法吗?
1条答案
按热度按时间ltskdhd11#
为什么总是在一个问题上花了半天的时间,找了几十个帖子和论坛,什么都没找到,最后决定问一个问题......几分钟后我终于找到了答案。
无论如何,纠正这个问题(found here)的一种方法是将渲染封装在
local
函数中,如下所示:现在,在
observe
结束之后仍然调用compute
,但是tmp变量具有正确的值:结果就是我想要的:
需要说明的是,我已经尝试过使用
local
函数,但是如果您不将id_box复制到另一个变量中(仅用于local
块),它将无法工作。