Make module output reactive

The example app below has two shiny modules. The first module displays a table with randomly generated values as well as an action button, which, when clicked, generates new values. The second module displays the data set generated in the first one.

How do I make the second table change with the first one?

Thank you.

app.R

library(shiny)
source("modules.R")

ui <- fluidPage(
  
  fluidRow(
    column(6, table1_moduleUI("table1")),
    column(6, table2_moduleUI("table2"))
    
  )
  
)

server <- function(input, output, session) {
  
  table1 <- callModule(table1_module, "table1")
  callModule(table2_module, "table2", table_data = table1$values)
}

shinyApp(ui, server)

modules.R

library(shiny)

# Module for table 1

table1_moduleUI <- function(id){
  ns <- NS(id)
  
  tagList(
    tableOutput(ns("table")),
    actionButton(ns("submit"), label = "Change values")
  )
}

table1_module <- function(input, output, session) {
  
  table <- reactiveValues()
  
  observeEvent(input$submit, {
    table$values <- replicate(3, rnorm(10))
  }, ignoreNULL = FALSE)
  
  output$table <- renderTable({
    table$values
  })
  
  return(table)
}


# Module for table 2

table2_moduleUI <- function(id){
  
  ns <- NS(id)
  tableOutput(ns("table"))
}

table2_module <- function(input, output, session, table_data){
  
  output$table <- renderTable({
    table_data
  })
}

What's happening is the button click in your table1 module is never leaving the confines of that module. Upon app startup, the call to table2_module receives the initial contents of the first module's table, but it is not re-executed as it is completely unaware of the button click.

The quickest way to fix this is to return an additional value from table1_module corresponding to the button click, and then creating an observeEvent in the main app's server function to call the second module after every click. As you venture in to the world of composing multiple modules that interact with each other, I'd highly recommend consulting the communication between modules article to set yourself up for success. We plan on adding additional articles covering additional best practices as the year progresses.

app.R

library(shiny)
source("modules.R")

ui <- fluidPage(
  
  fluidRow(
    column(6, table1_moduleUI("table1")),
    column(6, table2_moduleUI("table2"))
    
  )
  
)

server <- function(input, output, session) {
  
  table1 <- callModule(table1_module, "table1")
  
  observeEvent(table1$click, {
    callModule(table2_module, "table2", table_data = table1$values, table_click = table1$click)
  })
  
}

shinyApp(ui, server)

modules.R

library(shiny)

# Module for table 1

table1_moduleUI <- function(id){
  ns <- NS(id)
  
  tagList(
    tableOutput(ns("table")),
    actionButton(ns("submit"), label = "Change values")
  )
}

table1_module <- function(input, output, session) {
  
  table <- reactiveValues()
  
  observeEvent(input$submit, {
    table$values <- replicate(3, rnorm(10))
    table$click <- rnorm(1)
  }, ignoreNULL = FALSE)
  
  output$table <- renderTable({
    table$values
  })
  
  return(table)
}


# Module for table 2

table2_moduleUI <- function(id){
  
  ns <- NS(id)
  tableOutput(ns("table"))
}

table2_module <- function(input, output, session, table_data, table_click){
  
  output$table <- renderTable({
    table_data
  })
}
1 Like

I really appreciate it @rpodcast. I actually decided to start building shiny apps with modules after watching your presentation at the beginning of the year. I have a lot more shiny apps to make and am looking forward to studying the tutorials that you are going to release.

Also, I asked the same question on Stackoverflow. You might want to copy and paste your answer there too so I can mark it as a solution:

This topic was automatically closed 7 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.