簡體   English   中英

生成動態數量的元素時如何在閃亮渲染中強制評估?

[英]How to force evaluation in shiny render when generating dynamic number of elements?

我在 shiny 中生成了一個動態數量的valueBox ,這個數字可以根據用戶輸入而改變。 我設法用一個renderUI來處理這個問題,我在其中放置了所需數量的valueBoxOutput ,並且我有一個observe器,它將使用renderValueBox為它們提供內容。

我的問題是:由於某種原因, renderValueBox中的代碼實際上是在observe完成后執行的,所以因為renderValueBox處於循環中(具有動態數量)但是代碼是在之后對所有輸出執行的循環,我所有的輸出都會得到循環的最后一個值

這是一個最小的代表:

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)

這是結果:

代表的輸出

和控制台輸出:

控制台的輸出

如您所見,計算(以及一般的渲染)是在觀察函數結束后完成的,並且兩個輸出都將使用設置的最后一個 id_box(因此最后一個循環,box_2),而不是正確使用 box_1 和 box_2 .

我嘗試使用force ,在渲染之外計算 valueBox ,使用反應列表,沒有任何效果,因為無論我做什么,渲染都是在觀察之后評估的,所以無論如何只會使用最后一個循環值。

有誰知道在循環中強制執行的方法嗎? 或者看到另一種實現相同結果的方法?

為什么總是在一個問題上花了半天時間,找了幾十個帖子和論壇,一無所獲,最后決定問一個問題……幾分鍾后我終於找到了答案。

無論如何,糾正此問題的一種方法(在此處找到)是將渲染封裝在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")
  })

現在compute仍然在observe結束后被調用,但是 tmp 變量有正確的值:

日志控制台

結果是我想要的:

閃亮的結果

作為記錄,我已經嘗試使用local函數,但如果您不將 id_box 復制到另一個變量中,只是為了local集團,它將無法工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM