【问题标题】:Something unwanted extra, when creating Shiny UI elements (Shiny Dashboard boxes) in using a server side loop使用服务器端循环创建闪亮的 UI 元素(闪亮的仪表板框)时不需要的额外内容
【发布时间】:2021-10-06 18:56:30
【问题描述】:

我正在测试从服务器端使用循环动态创建闪亮 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”乘以盒子废话的数量是从哪里来的,我该如何摆脱它呢?

【问题讨论】:

    标签: r shiny shinydashboard


    【解决方案1】:

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

    Here 解释了为什么这是有利的。另见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)
    

    【讨论】:

    • 不工作。与我使用 for 循环的解决方案一样,在框旁边打印了相同的废话。
    • 这不是真的 - 我添加了一个 gif。
    • 我再次尝试了您的解决方案,现在废话确实消失了。这很奇怪,但无论如何,谢谢,您提供了一个可行的解决方案。
    【解决方案2】:

    由于“废话”位于列表对象的某个位置,我决定仔细研究一下。

    所以我开发了这个“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
    
        })
    
    })
    

    老实说,我认为这是一种错误的做法,必须有更好的方法来进行,但在有人在这里发布之前,这似乎是要走的路。至少废话消失了:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-09
      • 1970-01-01
      • 2018-05-30
      • 2021-09-05
      相关资源
      最近更新 更多