在使用服务器端循环创建 Shiny UI 元素(Shiny Dashboard 框)时,不需要额外的东西

Something unwanted extra, when creating Shiny UI elements (Shiny Dashboard boxes) in using a server side loop

我正在测试通过服务器端的循环动态创建 Shiny UI 元素的方法,用户可以控制实际生成的元素数量。在我的例子中,元素是带有两个下拉菜单和一个按钮的 Shiny Dashboard 框。一切正常,除了打印出一些额外的东西,正如您从图像中看到的那样:

我的 ui.r 看起来如下:

library(shiny)
library(shinydashboard)
shinyUI(dashboardPage(
    dashboardHeader(title = 'The Box Experiment'),

    # Sidebar with a slider input for number of bins
    dashboardSidebar(
        
            sliderInput("numberOfBoxes",
                        "Number of boxes:",
                        min = 1,
                        max = 50,
                        value = 5)
        ),
    dashboardBody(uiOutput("boxes"))
    )        
    )

...和 ​​server.r 看起来如下:


library(shiny)
library(shinydashboard)

shinyServer(function(input, output) {

    output$boxes <- renderUI({
        
        boxlist = c()
        for(i in 1:input$numberOfBoxes) {
            ddmenu1 <- selectInput(paste0("ddmenu1_in_box",i), "Animal", list('cat', 'dog', 'rabbit'))
            ddmenu2 <- selectInput(paste0("ddmenu2_in_box",i), "Color", list('red', 'blue', 'green'))
            button <- actionButton(paste0("justabutton_in_box",i), "Click me!")
            boxlist <- c(boxlist,column(1, box(ddmenu1, ddmenu2, button)))
        }
        
        boxlist

    })

})

那么这个“div col-sm-1”乘以箱子数量的垃圾是从哪里来的,我该如何摆脱它?

我建议使用 lapply 而不是使用 for 循环。

is explained why this is advantageous. Also see this overview.

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(title = 'The Box Experiment'),
    dashboardSidebar(
      sliderInput("numberOfBoxes",
                "Number of boxes:",
                min = 1,
                max = 50,
                value = 5)
  ),
  dashboardBody(uiOutput("boxes"))
) 

server <- function(input, output, session) {
  output$boxes <- renderUI({
    lapply(seq_len(input$numberOfBoxes), function(i){
      box(
        selectInput(paste0("ddmenu1_in_box", i), "Animal", list('cat', 'dog', 'rabbit')),
        selectInput(paste0("ddmenu2_in_box", i), "Color", list('red', 'blue', 'green')),
        actionButton(paste0("justabutton_in_box", i), "Click me!")
      )
    })
  })
}

shinyApp(ui, server)

既然“废话”存在于列表对象的某处,我决定仔细研究一下。

所以我开发了这个“hack”来用空字符串覆盖文本:

ui.r(无修改)

library(shiny)
library(shinydashboard)
shinyUI(dashboardPage(
    dashboardHeader(title = 'The Box Experiment'),

    # Sidebar with a slider input for number of bins
    dashboardSidebar(
        
            sliderInput("numberOfBoxes",
                        "Number of boxes:",
                        min = 1,
                        max = 50,
                        value = 5)
        ),
    dashboardBody(uiOutput("boxes"))
    )   
    )

server.r(这次包括一个覆盖不需要的字符串的循环)

library(shiny)
library(shinydashboard)

shinyServer(function(input, output) {

    output$boxes <- renderUI({
        
        boxlist = list()
        for(i in 1:input$numberOfBoxes) {
            ddmenu1 <- selectInput(paste0("ddmenu1_in_box",i), "Animal", list('cat', 'dog', 'rabbit'))
            ddmenu2 <- selectInput(paste0("ddmenu2_in_box",i), "Color", list('red', 'blue', 'green'))
            button <- actionButton(paste0("justabutton_in_box",i), "Click me!")
            boxlist <- append(boxlist,(column(1, box(ddmenu1, ddmenu2, button))))
        }
        
        #Let's go through every attribute
        for(i in 1:length(attributes(boxlist)$names)) {
            #If the attribute name is NOT "children"
            if(attributes(boxlist)$names[i] != "children") {
                #...and the length of corresponding variable "name" equals one (text string)...
                if(length(boxlist[i]$name) == 1) {
                    boxlist[i]$name <- ''
                }
                #...and the length of corresponding variable "attribs$class" equals one (text string)...
                if(length(boxlist[i]$attribs$class) == 1) {
                    boxlist[i]$attribs$class <- ''
                }
            }
        }
         
        boxlist

    })

})

老实说,我认为这样做是错误的,必须有更好的方法来进行,但是直到有人 post 在这里,这似乎是要走的路。至少废话不见了: