0

I have a set of dynamic UI forms being generated in tabs. I have used dynamic observeEvents to check which form is being saved. Please see the code below

library(shiny)

ui <- fluidPage(
  actionButton("generate_tab","Generate Tabs"),
  tabsetPanel(id="tabs",
              uiOutput('tabsN')),
  dataTableOutput("saved_tabs_output")
)

server <- function(input, output, session) {
  rv<- reactiveValues(no_of_tabs =0)

  #generating the UI dynamically
 observeEvent(input$generate_tab,{
   rv$no_of_tabs <- rv$no_of_tabs + 1
   appendTab(inputId = "tabs", 
             tabPanel(title = paste0("Tab_",rv$no_of_tabs),
             selectInput(paste0("Input",rv$no_of_tabs),paste0("Input",rv$no_of_tabs), choices = c('',LETTERS), selected = NULL),
             actionButton(paste0("submit_input",rv$no_of_tabs),"submit input")
             )
   )})

# Reading the inputs upon clicking of Submit Input in each tab
   #dynamic Observe Event needs to be set up dependent on number of Tabs (rv$no_of_tabs)

   observeEvent(lapply(paste0("submit_input",1:rv$no_of_tabs), function(x){input[[x]]

   }
   ),{
     rv$inputs <-sapply(paste0("Input",1:rv$no_of_tabs), 
                        function(x)input[[x]])

        },ignoreInit = TRUE  )



   output$saved_tabs_output <- renderDataTable({
     as.data.frame(rv$inputs) 
   })


}

shinyApp(ui, server)

because multiple submit-button clicks are being checked in one observeEvent lapply formulation, it accepts inputs from non-submitted forms as well. Here is an example

Step 1: Hit Generate tabs 4 times to generate Tab1,Tab2,Tab3,Tab 4. Click Tab 1 enter image description here

Step 2: Select B in Tab 1. Do NOT press Submit enter image description here

Step 3: Select D in Tab 4 and Hit Submitenter image description here

Desired output is that only Input4 is updated and not input1, however in this case, both B and D are saved. Any pointers as to how one can fix this?

ashleych
  • 1,042
  • 8
  • 25
  • It is much easier if you have only one observer to process all the clicks of the dynamically created elements. Look at these couple of examples [here](https://stackoverflow.com/questions/40631788/shiny-observe-triggered-by-dynamicaly-generated-inputs/40643541#40643541) and [here](https://stackoverflow.com/questions/40547786/shiny-can-dynamically-generated-buttons-act-as-trigger-for-an-event/40558301#40558301) – Geovany Mar 31 '19 at 20:35

1 Answers1

1

Geovany's comment helped. I was also helped by this link. The trick was to associate just one observer with each Submit button.

Here is the code that works, in case it is useful for anyone

library(shiny)
library(purrr)
options(shiny.reactlog = TRUE)
ui <- fluidPage(
  actionButton("generate_tab", "Generate Tabs"),
  tabsetPanel(id = "tabs",
              uiOutput('tabsN')),
  verbatimTextOutput("rvInput")

)

server <- function(input, output, session) {
  # browser()
  rv <- reactiveValues(no_of_tabs = 0L,
                       inputs = list()
                       )

  #generating the UI dynamically
  observeEvent(input$generate_tab, {
    rv$no_of_tabs <- rv$no_of_tabs + 1
    appendTab(inputId = "tabs",
              tabPanel(
                title = paste0("Tab_", rv$no_of_tabs),
                selectInput(
                  paste0("Input", rv$no_of_tabs),
                  paste0("Input", rv$no_of_tabs),
                  choices = c('', LETTERS),
                  selected = NULL
                ),
                actionButton(paste0("submit_input", rv$no_of_tabs), "submit input")
              ))
  })

  observe({
    lapply(1:rv$no_of_tabs, function(x) {
      observeEvent(input[[paste0("submit_input", x)]], {
        rv$inputs[[x]] <- input[[paste0("Input", x)]]
      })
    })
  })

  output$rvInput <- renderPrint({
    rv$inputs
  })

}

shinyApp(ui, server)
ashleych
  • 1,042
  • 8
  • 25