Shiny action button with modules

I am trying to do a simple code where the final goal to generate multiple charts after the button is clicked.

Currently, I am giving all the inputs (such as date etc.) inside the code itself. The plan is to make that available through the GUI. However, in the GUI, I also want to include a button so that the actual RStudio code (which includes fetching the data from database, cleaning and organizing the data and plotting the charts take place) runs. The button is clicked after the user has given all the inputs. No charts should be plotted until the user clicks the button.

As there are multiple charts that will be plotted and the number of charts vary depending on the user inputs, I am using Shiny modules and it is working fine when I run the code from RStudio with no GUI.

I am wondering how should I make the code run using the GUI and especially actionButton (the button after clicking which all the charts will be presented).

 ui <- fluidPage(
   selectInput("select1", label = h3("Select 1"),
               choices = list("Option1", "Option2", "Option3"),
               selected = NULL),
   textInput("select2", label = h3("Select2")),
   textInput("select3", label = h3("Select3"), value = "13315"),
   dateInput("end_date", label = h3("Enter end date (default is today)"), value = NULL),
   numericInput("num_days", label = h3("Enter the number of days for trend"), value = 30),
   actionButton("start", "Submit (draw plots)"),
   textOutput("txt_output"),
   fluidRow(
     column(12,
            tableOutput('table')
     )),
   
   **fluidRow(**
**     lapply(1:5, function(i) plotting_module_UI(unique(getData$vcStructure)[i]))**
**   )**
 )

plotting_module_UI function is as follows.

 plotting_module_UI <- function(id) {
   
   message("I am in module_UI. Am I expected to be here?")
   
   ns <- NS(id)
   column(10,
   fluidRow(column(2,
          selectInput(ns("s_groups"), "Group", c("Group1", "Group2", "Group3", "Group4", "Group5"), selected = NULL, multiple = FALSE, selectize = TRUE, width = 1000, size = NULL)
   ),
   column(2,
          selectInput(inputId = ns("s_xaxis"), label = "X - Axis", choices = c("Option1", "Option2", "Option3", "Option4", "Option4"), selected = "Option1", multiple = FALSE, selectize = TRUE, width = NULL, size = NULL)
   )),
   plotlyOutput(ns("s"), height = "800px", width = "1500px")
   )
   
   message("I am in module_UI. If seeing this message, it means that you must be seeeing the charts.")
 }

I have server function too and it is working as required. Adding the debug messages in the code and following them, i learned that the fluidRow line in ui function is never implemented.

Please let me know if there is something I am missing here. I am relatively new to R programming.

Unless I misunderstand the issue, I think the shiny guide on "Stop reactions with isolate()" will be useful.

It outlines how to use actionButton in conjunction with isolate when a plot is displayed.

If I understood you correctly, basically what you want to achieve is that there are many plots, but input elements that are common to all of them.

From what I believe to know, Shiny modules might not be the right tool here (or I don't know how to leverage them correctly :smile:) , because they create own namespaces for their elements, which are therefore not meant to be shared with other components.

So, you could e.g. create a module that has some input elements (selectInput, ...) and some output elements (plotOutput, ...) and put this module each into an own tab panel in your Shiny app. Then each "instance" of this module would have its own input elements in their respective namespaces. But this seems not to be what you want.

Wouldn't something like this work for you, too?

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fluidRow(column(4, 
        selectInput("select1", label = "Select an option",
                    choices = list("Option 1", "Option 2", "Option 3"),
                    selected = NULL),
        actionButton("button", "Create plots")
      )
    )),
    mainPanel(
      fluidRow(
        column(4, plotOutput("plot1")),
        column(4, plotOutput("plot2")),
        column(4, plotOutput("plot3"))
      )
    )
  )
)

server <- function(input, output, session) {
  observeEvent(input$button, {
    
    output$plot1 <- renderPlot({
      plot(rnorm(10), rnorm(10), main = paste0("Plot #1: ", isolate(input$select1)))
    })
    
    output$plot2 <- renderPlot({
      plot(rnorm(20), rnorm(20), main = paste0("Plot #2: ", isolate(input$select1)))
    })
    
    if (input$select1 == "Option 3") {
      output$plot3 <- renderPlot({
        plot(rnorm(30), rnorm(30), main = paste0("Plot #3: ", isolate(input$select1)))
      })
    } else {
      output$plot3 <- NULL
    }
    
  })
}

shinyApp(ui, server)
1 Like

a part of the code involves gathering data for multiple parameters from the data base. The number of parameters that are read from the data base depends on the inputs opted by the user. I am reading the data for all the parameters in one go and then using lapply and calling shiny module to plot. The shiny module for organizing the data is being called correctly and is doing the job. However, the corresponding UI module is not being called properly.

This code will work if you have a fixed and small number of charts. If the number of charts that I am going to plot is huge and dependent on the inputs chosen by the user then it won't work.

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