Search code examples
rshinyshinydashboard

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


I am testing out to way of creating Shiny UI elements dynamically with a loop from the server side in a way that the user could control how many elements are actually produced. In my case the element is Shiny Dashboard box with two dropdown menus and one button. Everything works fine, except something extra is printed out as you can see from the image: Unwanted extra text next to the boxes

My ui.r looks as follows:

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"))
    )        
    )

...and server.r looks as follows:


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

    })

})

So where does this "div col-sm-1" times the number of boxes crap come from, and how do I get rid of it?


Solution

  • I'd recommend working with lapply rather than using a for-loop.

    Here 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)
    

    result