Search code examples
rdynamicshinydropdownshinydashboardplus

Creation and deletion of dynamic boxes in R Shiny using shinydashboardplus package (boxDropdownItem)


I'm trying to create a page to include and exclude boxes dynamically using boxDropdownItem from shinydashboardplus package, but the application is crashing, could someone help me please?

*Solutions using javascript are also welcome :)

Here my code:

shinyApp(
        ui = dashboardPage(
        dashboardHeader(),  
        dashboardSidebar(),
        dashboardBody(
        uiOutput("boxes")
        )
),

server = function(input, output) {

        rvs = reactiveValues(boxDropdownItem = list(), observers = list())

        output$boxes <- renderUI({
        for(i in 1:5) {
                rvs$boxDropdownItem[[i]] =
                column(width = 12,
                        box(    id = paste("box",i),
                                title = paste("box",i),
                                width = 4,
                                status = NULL,
                                dropdownMenu = boxDropdown(
                                        icon = icon("ellipsis-v"),
                                        boxDropdownItem(id = paste0("del",i), "Delete")
                                )
                        )
                )
        }

        rvs$observers = lapply(1:(length(rvs$boxDropdownItem)),function(i) {
  
        observeEvent(input[[paste0("del",i)]],{ 
                rvs$observers <- rvs$observers[-i]
                rvs$boxDropdownItem <- rvs$boxDropdownItem[-i]
        })
        }) 

        do.call(fluidRow, rvs$boxDropdownItem) 
})

}
)

Solution

  • You need to first create the boxes as a reactiveValues object. Then you can control what you display in renderUI. I have shown here for 3 boxes. You can modify it to dynamic number. Try this

    library(shinydashboardPlus)
    
    shinyApp(
      ui = shinydashboard::dashboardPage(title = "My Box Dropdown",
        dashboardHeader(),  
        dashboardSidebar(),
        dashboardBody(
          uiOutput("boxes")
        )
      ),
      
      server = function(input, output) {
        
        rvs = reactiveValues(boxDropdownItem = list(), observers = list(), tmp=list())
        
        observe({
          for(i in 1:3) {
            rvs$boxDropdownItem[[i]] <-
              box(id = paste0("box",i),
                  title = paste("box",i),
                  width = 12,
                  status = "warning",
                  solidHeader = TRUE,
                  collapsible = TRUE,
                  dropdownMenu = boxDropdown(
                    icon = icon("ellipsis-v"),
                    boxDropdownItem("Click me", id = paste0("dropdownItem",i), icon = icon("heart")),
                    dropdownDivider(),
                    boxDropdownItem(id = paste0("del",i), "Delete")
                  ),
                  paste("My Box",i)
              )
            
          }
          
        })
        
        output$boxes <- renderUI({
          if (length(rvs$tmp)>0){
            rvs$boxDropdownItem[!(rvs$boxDropdownItem %in% rvs$tmp)]
          } else rvs$boxDropdownItem
        })
        
        lapply(1:3, function(i) {
          observeEvent(input[[paste0("del",i)]],{
            rvs$tmp[[i]] <<- rvs$boxDropdownItem[[i]]
          }, ignoreInit = TRUE)
          
          
          observeEvent(input[[paste0("dropdownItem",i)]], {
            showNotification("Hello", duration = i, type = "error")
          })
    
        })
        
      }
    )
    

    The picture below shows box 2 deleted.

    output