I am trying to find a systematic, robust manner for transmitting reactive data between R modules in a two-way flow that I can use as a template going forward. How to transmit data between modules isn't clear to me yet.
In running the example R Shiny code shown at the bottom of this post, the first module mod1
multiplies the base dataframe df
values by the user slider input value, and the second module mod2
adds 10 to all of the values from mod1
. Then, via the observe()
in the mod1_server()
function, the first column of the mod2
table is transmitted back to mod1
and the added column in the table is named "colA_mod2". All works fine so far. You can run the code posted at the bottom and see how this works.
However, how do you multiply the values in "colA_mod2" by 100 and transmit those values back to mod2
and append those values as column to the mod2
table, to be labelled as "colA_mod2_mod1"? I think if I can see how this step works I can finally get my head around transmitting values between modules in both directions.
Code:
library(shiny)
library(DT)
mod1_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod2_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod1_server <- function(input, output, session, common) {
new_dat <- reactive({
df <- common$df
svc <- common$svc()
df * as.numeric(svc)
})
# the below transmits mod2 data back to mod1
observe({
common$mod1_dat <- new_dat()
common$colA_mod2 <- common$mod2_table$A
})
output$tbl <- renderDT({
dat <- new_dat()
dat$colA_mod2 <- common$colA_mod2
dat
})
}
mod2_server <- function(input, output, session, common) {
output$tbl <- renderDT({
mod1_dat <- common$mod1_dat
dat <- data.frame(mod1_dat + 10)
common$mod2_table <- dat
dat
})
}
ui <- fluidPage(
mainPanel(
h5(strong("Base table:")),
DTOutput("table"),
h5(strong(paste(
"Module 1 multiplies slider input by values in above table",
"and then tacks on column A from mod2 called `ColA_mod2´:"))),
sliderInput("svc", "", min = 0, max = 10, value = 1),
mod1_ui("mod1"),
h5(strong(paste(
"Module 2 then adds 10 to those Module 1 products [and then tacks on",
"a new column called `ColA_mod2_mod1` which is `ColA_mod2` from mod1",
"multipled by 100]:"))),
mod2_ui("mod2")
)
)
server <- function(input, output, session) {
common <- reactiveValues(df = data.frame(A = 1:2, B = 3:4))
output$table <- renderDT({datatable(common$df)})
common$svc <- reactive(input$svc)
callModule(mod1_server, "mod1", common)
callModule(mod2_server, "mod2", common)
}
shinyApp(ui, server)
Try this
library(shiny)
library(DT)
mod1_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod1_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
new_dat <- reactive({
df <- common$df
svc <- common$svc()
df * as.numeric(svc)
})
# the below transmits mod2 data back to mod1
observe({
common$mod1_dat <- new_dat()
common$colA_mod2 <- common$mod2_table$A
})
output$tbl <- renderDT({
dat <- new_dat()
dat$colA_mod2 <- common$colA_mod2
dat
})
})
}
mod2_ui <- function(id) {
ns <- NS(id)
DTOutput(ns("tbl"))
}
mod2_server <- function(id, common) {
moduleServer(id, function(input, output, session) {
output$tbl <- renderDT({
mod1_dat <- common$mod1_dat
dat <- data.frame(mod1_dat + 10)
if (!is.null(common$colA_mod2)) dat$colA_mod2_mod1 <- common$colA_mod2 * 10
common$mod2_table <- dat
dat
})
})
}
ui <- fluidPage(
mainPanel(
h5(strong("Base table:")),
DTOutput("table"),
h5(strong(paste(
"Module 1 multiplies slider input by values in above table",
"and then tacks on column A from mod2 called `ColA_mod2´:"))),
sliderInput("svc", "", min = 0, max = 10, value = 1),
mod1_ui("mod1"),
h5(strong(paste(
"Module 2 then adds 10 to those Module 1 products [and then tacks on",
"a new column called `ColA_mod2_mod1` which is `ColA_mod2` from mod1",
"multipled by 100]:"))),
mod2_ui("mod2")
)
)
server <- function(input, output, session) {
common <- reactiveValues(df = data.frame(A = 1:2, B = 3:4))
output$table <- renderDT({datatable(common$df)})
common$svc <- reactive(input$svc)
mod1_server("mod1", common)
mod2_server("mod2", common)
}
shinyApp(ui, server)