Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic number of actionButtons tied to unique observeEvent

Tags:

r

shiny

I'd like to generate a dynamic number of actionButtons, and then have each generated button print its number to the console. This is my best attempt so far, but I still can't get the observeEvent for each of the first 10 buttons to recognize the button clicks. How do I tie the buttons to an observeEvent?

library(shiny)

ui <- basicPage(
  fluidRow(
    actionButton(inputId = "add_button",
                 label = "Add Button")
    ),
  uiOutput("more_buttons")
)

server <- function(input, output){

  rvs <- reactiveValues(buttons = list(actionButton(inputId = "button1",
                                               label = 1)))

  observeEvent(eventExpr = input$add_button,
               handlerExpr = {
                 len <- length(rvs$buttons) + 1
                 rvs$buttons[[len]] <- actionButton(inputId = paste0("button",len),
                                             label = len)
               })

  output$more_buttons <- renderUI({
    do.call(fluidRow, rvs$buttons)
  })

  # This is the part that doesn't work
  for(ii in 1:10){
    observeEvent(eventExpr = input[[paste0("button",ii)]],
                 handlerExpr = print(ii))
  }

}

shinyApp(ui, server)
like image 363
Sam Helmich Avatar asked Dec 08 '15 13:12

Sam Helmich


Video Answer


2 Answers

Your really close, just wrap the observeEvent part in local.

library(shiny)

ui <- basicPage(
  fluidRow(
    actionButton(inputId = "add_button",
                 label = "Add Button")
  ),
  uiOutput("more_buttons")
)

server <- function(input, output){

  rvs      <- reactiveValues(buttons = list(actionButton(inputId = "button1",
                                                    label = 1)))

  observeEvent(eventExpr = input$add_button,
               handlerExpr = {
                 len      <- length(rvs$buttons) + 1
                 rvs$buttons[[len]] <- actionButton(inputId = paste0("button",len),
                                                    label = len)
               })

  output$more_buttons <- renderUI({
    do.call(fluidRow, rvs$buttons)
  })

  observeEvent(rvs$buttons,{
    for(ii in 1:length(rvs$buttons)){
      local({
        i <- ii
        observeEvent(eventExpr = input[[paste0("button",i)]],
                     handlerExpr = {print(sprintf("You clicked btn number %d",i))})
      })
    }
  })

}

shinyApp(ui, server)
like image 169
RmIu Avatar answered Oct 20 '22 04:10

RmIu


Let the inputIds of the buttons to follow a pattern like "button1", "button2", "button3", use regex to isolate those inputIds from the 'input' object in the observeEvent trigger, and convert the result to a list:

 observeEvent(
     lapply(
        names(input)[grep("button[0-9]+",names(input))],
        function(name){
           input[[name]]
        }
     ),
    {
      code to run when any button with inputId matching the regex is pressed
    }
  )
like image 38
Victor Burnett Avatar answered Oct 20 '22 04:10

Victor Burnett