使用 insertUI 添加几个闪亮模块时出现问题

problem in adding several shiny modules using insertUI

我构建了一个闪亮的应用程序,它需要根据一些我只能实时知道的参数动态添加 UI 的片段。我对我的需求进行了简单的重建,遇到了下面描述的问题

所以在我的示例中,我有一个名为 mblock 的模块。为了这个例子,它只显示一个文本。要显示的实际文本在 运行 时间决定,文本(以及块)的数量也将在 运行 时间

决定

对于具体示例,我将文本设置为包含所有要显示的文本的固定向量,但实际上它将被计算为反应对象。代码如下:

library(shiny)

#block module
mblockUI = function(id) {
    ns = NS(id)
    fluidRow(
        textOutput(ns("text"))
    )
}

mblock = function(input,output,session,actual_text) {
    output$text = renderText({actual_text})
}


# Define the main ui 
ui <- fluidPage(
    uiOutput("all_blocks"),
    actionButton("submit","submit")
)

# Define server logic
server <- function(input, output) {
    texts = c("aaaa","bbbb","cccc") #this is a sample vector of texts to be shown in blocks

    output$all_blocks = renderUI({
        for(i in 1:length(texts)) {
            mname = paste0("block",i)  #block name to be created (the name of the module)
            #print(mname)
            insertUI("#submit","beforeBegin",mblockUI(mname))  #adding the ui
            #now adding the server side of each block
            #also passing the text to be shown
            callModule(mblock,mname,texts[i])     
        }
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

问题是所有的块都显示相同的文本(最后一个)。我不明白为什么

对如何修复代码有任何想法吗?我想念什么 (闪亮版本 1.4.0)

首先,insertUI 能够“独立”工作,不需要 renderUI。您可以将它放在 observe 环境中。但是,请注意 insertUI 的输出,因为它是持久的,如该函数的文档中所述:

Unlike renderUI(), the UI generated with insertUI() is persistent: once it's created, it stays there until removed by removeUI(). Each new call to insertUI() creates more UI objects, in addition to the ones already there (all independent from one another). To update a part of the UI (ex: an input object), you must use the appropriate render function or a customized reactive function.

我不知道为什么,但是 for 循环不起作用(如您的示例所示),而 lapply 起作用(参见 示例)。

下面是您的示例,其中包含这些更正:

library(shiny)

#block module
mblockUI = function(id) {
  ns = NS(id)
  fluidRow(
    textOutput(ns("text"))
  )
}

mblock = function(input,output,session,actual_text) {
  output$text = renderText({actual_text})
}


# Define the main ui 
ui <- fluidPage(
  actionButton("submit","submit")
)

# Define server logic
server <- function(input, output) {
  texts = c("aaaa","bbbb","cccc") #this is a sample vector of texts to be shown in blocks
  
  observe({
    lapply(1:length(texts), function(i) {
      mname = paste0("block",i)  #block name to be created (the name of the module)
      #print(mname)
      insertUI("#submit","beforeBegin",mblockUI(mname))  #adding the ui
      #now adding the server side of each block
      #also passing the text to be shown
      callModule(mblock,mname,texts[i])     
    })
  })
}

# Run the application 
shinyApp(ui = ui, server = server)