Method for using removeUI in for loop

I'm dynamically generating inputs using a custom function render_panels that creates a wellPanel with a selectizeInput and actionButton contained within, the actionButton removes the entire wellPanel using removeUI by using the id of the div as the selector. I also have a global add button to add new wellPanel.

I have a method to remove the wellPanel by observing the remove button event for each panel, then using removeUI and specifying corresponding div id as selector, but I'm wondering if there is a more efficient method to do this with either for loop or vectorized approach.

See reprex:

library(shiny)


render_panels <- function(n, removed_panels){
  
  make_panels <- function(n){
    panels <- tags$div(id = n,
               wellPanel(
                 selectizeInput(inputId = paste0("dropdown", n), label = paste0("dropdown", n), choices = c("a", "b", "c"), selected = NULL),
                             actionButton(paste0("remove", n), label = paste0("remove", n))
               )
      )
  }
  
  ui_out <- vector(mode = "list", length = n)
  
  for(i in seq_along(ui_out)){
    if(i %in% removed_panels) next
    ui_out[[i]] <- tagList(
      make_panels(n = i)
    )
  }
  
  return(ui_out)
}

ui <- fluidPage(
  fluidRow(
    column(width = 6,
      actionButton("add", label = "add"),
      uiOutput("mypanels")
    )
  )
)

server <- function(input, output, session){
  
  removed <- reactiveValues(
    values = list()
  )
  
  observeEvent(input$remove1,{
    removed$values <- c(removed$values, 1)
    removeUI(
      selector =  "div#1",  immediate = TRUE,
    )
  }, once = TRUE)

  observeEvent(input$remove2,{
    removed$values <- c(removed$values, 2)
    removeUI(
      selector =  "div#2",  immediate = TRUE,
    )
  }, once = TRUE)

  observeEvent(input$remove3,{
    removed$values <- c(removed$values, 3)
    removeUI(
      selector =  "div#3",  immediate = TRUE,
    )
  }, once = TRUE)

  
  output$mypanels <- renderUI({
      render_panels(n = input$add, removed_panels = removed$values)
  })
  
}

shinyApp(ui, server)

As you can see, if there are 100 wellPanels generated, I'd have to use 100 observeEvent, not what we want...here is my attempt at for loop:

I'd like to replace all observeEvent calls with something like below, but cannot seem to get things working.

observe({
    req(input$remove1)
    for(i in seq_len(input$add)){
      if(input[[paste0("remove", i)]] == 1){
        removeUI(selector = paste0("div#", i), immediate = TRUE)
      }
    }
  })

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.