How to collate the data output of multiple shiny modules that are called dynamically by the user

shiny-modules

#1

I have a working shiny module that allows the user to input certain parameters then run a forecasting model which then returns a single dataframe to the main app.

I'm trying to setup the app to allow the user to launch as many of these modules as they want to model several different 'scenarios' and then be able to compare the results of each.

I'm trying to achieve this by dynamically launching each scenario module using insertTab inside an observer that looks out for a button click and then store the data the module produces inside a reactiveValues list. I then plan to combine all the data returned and chart the differences of each scenario the user has run.

Relevant code:

rv <- reactiveValues()

observeEvent(input$add_scenario, {
    num <- as.numeric(input$add_scenario)
    id <- paste0("s", num)
    label <- paste("Scenario", num)
    
    insertTab(
      inputId = "tabs",
      target = paste("Scenario", num - 1),
      position = "after",
      tabPanel(label, model_UI(id)),
      select = FALSE
    )
    
    rv[[id]] <- callModule(model, id)
  })

The data from the module is passed back as a reactive reactive({ module_output() }) but this value will initially be NULL until the user inputs their parameters and hits 'run' on an actionButton inside the module.

I'm having difficulty trying to access the data returned to the reactiveValues list. I want to bind_rows() on the items in rv that are not NULL i.e. data returned from any modules where the user has run a model.

The module adds a unique identifier column to indicate which scenario the data came from so if I bind_rows() on all non NULL data I can then chart the differences by grouping by scenario.

If anyone has a solution to this or can suggest a better method I'd be very appreciative!

Thanks.

EDIT purrr to the rescue.

It looks like the following code does the trick of combining the non-NULL items in the reactiveValues list into a single df:

scenario_outputs <- reactive({
    so <- reactiveValuesToList(rv)
    map_df(so, ~ .x())
  })