R语言 当生成动态数量的元素时,如何在闪亮渲染中强制求值?

gk7wooem  于 2022-12-25  发布在  其他
关注(0)|答案(1)|浏览(121)

我在我的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列表,但没有任何效果,因为无论我做什么,渲染都是在观察之后评估的,所以无论如何,只有最后一个循环值才会被使用。
有人知道在循环中强制执行的方法吗?或者看到另一种实现相同结果的方法吗?

ltskdhd1

ltskdhd11#

为什么总是在一个问题上花了半天的时间,找了几十个帖子和论坛,什么都没找到,最后决定问一个问题......几分钟后我终于找到了答案。
无论如何,纠正这个问题(found here)的一种方法是将渲染封装在local函数中,如下所示:

observe({
    print("observe")
    for(id_box in data$ids) {
      print(paste("observe - ", id_box))
      local({
        tmp <- id_box
        output[[tmp]] <- shinydashboard::renderValueBox(valueBox(tmp, compute(tmp), icon = icon("circle-info"), color = "teal"))
      })
    }
    print("end observe")
  })

现在,在observe结束之后仍然调用compute,但是tmp变量具有正确的值:

结果就是我想要的:

需要说明的是,我已经尝试过使用local函数,但是如果您不将id_box复制到另一个变量中(仅用于local块),它将无法工作。

相关问题