首页 > 解决方案 > 使用 insertUI 添加几个闪亮模块的问题

问题描述

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

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

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

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)

标签: rshinyshinymodules

解决方案


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

与 renderUI() 不同,使用 insertUI() 生成的 UI 是持久的:一旦创建,它就会一直保留在那里,直到被 removeUI() 删除。对 insertUI() 的每次新调用都会创建更多的 UI 对象,除了已经存在的对象(都相互独立)。要更新 UI 的一部分(例如:输入对象),您必须使用适当的渲染函数或自定义的反应函数。

我不知道为什么,但是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)

推荐阅读