I am working with a rather larger Shiny app with several modules. Each tab in the app is its own module. Some of the tabs have some shared inputs, along with distinct inputs to their own tabs.
This is what I need: when a user changes an input in one of the shiny modules, the inputs that are the same across modules need to change as well. This is so that the user doesn't need to keep changing the inputs across tabs when they already changed the input in one tab. Also, ideally the code would not execute until the user navigates to the tab.
Some resources that have given me ideas are the following:
Below I have written some example code of what I am trying to do. Any help is much appreciated. I am hoping a shiny master finds this post. So far, I have been unsuccessful.
library(shiny)
common_inputs_UI <- function(id) {
ns <- NS(id)
tagList(
selectInput(
ns('common1'),
'Common 1',
c('A', 'B', 'C', 'D')
),
selectInput(
ns('common2'),
'Common 2',
c('A2', 'B2', 'C2', 'D2')
)
)
}
common_inputs <- function(input, output, session) {
return(
list(
common1 = reactive({ input$common1 }),
common2 = reactive({ input$common2 })
)
)
}
test_one_UI <- function(id) {
ns <- NS(id)
tagList(
common_inputs_UI('test1'),
selectInput(
'test1_select',
'Test 1 Select',
c('Fee 1', 'Fi 1', 'Fo 1', 'Fum 1')
)
)
}
test_one <- function(input, output, session, default_inputs) {
ns <- session$ns
observe({
updateSelectInput(
session,
'common1',
selected = default_inputs$common1()
)
updateSelectInput(
session,
'common2',
selected = default_inputs$common2()
)
})
}
test_two_UI <- function(id) {
ns <- NS(id)
tagList(
common_inputs_UI('test2'),
selectInput(
'test2_select',
'Test 2 Select',
c('Fee 2', 'Fi 2', 'Fo 2', 'Fum 2')
)
)
}
test_two <- function(input, output, session, default_inputs) {
ns <- session$ns
observe({
updateSelectInput(
session,
'common1',
selected = default_inputs$common1()
)
updateSelectInput(
session,
'common2',
selected = default_inputs$common2()
)
})
}
test_three_UI <- function(id) {
ns <- NS(id)
tagList(
common_inputs_UI('test3'),
selectInput(
'test3_select',
'Test 3 Select',
c('Fee 3', 'Fi 3', 'Fo 3', 'Fum 3')
)
)
}
test_three <- function(input, output, session, default_inputs) {
ns <- session$ns
observe({
updateSelectInput(
session,
'common1',
selected = default_inputs$common1()
)
updateSelectInput(
session,
'common2',
selected = default_inputs$common2()
)
})
}
ui <- fluidPage(
tabsetPanel(
type = 'tabs',
tabPanel(
'Test One',
test_one_UI('test1')
),
tabPanel(
'Test Two',
test_two_UI('test2')
),
tabPanel(
'Test Three',
test_three_UI('test3')
)
)
)
server <- function(input, output, session) {
common_inputs_mod1 <- callModule(common_inputs, 'test1')
common_inputs_mod2 <- callModule(common_inputs, 'test2')
common_inputs_mod3 <- callModule(common_inputs, 'test3')
t1 <- callModule(test_one, 'test1', common_inputs_mod1)
t2 <- callModule(test_two, 'test2', common_inputs_mod2)
t3 <- callModule(test_three, 'test3', common_inputs_mod3)
}
shinyApp(ui, server)
To display the same common input in all tabs, you need to use the same common_inputs
in your calls to different modules (also suggested by @Limey in comments). To use one common input from tab1 and be free to choose other inputs in other tabs, you can use common_inputs_mod1
in all three calls. From your MRE, you can use three observeEvents to provide common inputs from any tab. Try this
server <- function(input, output, session) {
common_inputs_mod1 <- callModule(common_inputs, 'test1')
common_inputs_mod2 <- callModule(common_inputs, 'test2')
common_inputs_mod3 <- callModule(common_inputs, 'test3')
observeEvent(common_inputs_mod1, {
t1 <- callModule(test_one, 'test1', common_inputs_mod1)
t2 <- callModule(test_two, 'test2', common_inputs_mod1)
t3 <- callModule(test_three, 'test3', common_inputs_mod1)
})
observeEvent(common_inputs_mod2, {
t1 <- callModule(test_one, 'test1', common_inputs_mod2)
t2 <- callModule(test_two, 'test2', common_inputs_mod2)
t3 <- callModule(test_three, 'test3', common_inputs_mod2)
})
observeEvent(common_inputs_mod3, {
t1 <- callModule(test_one, 'test1', common_inputs_mod3)
t2 <- callModule(test_two, 'test2', common_inputs_mod3)
t3 <- callModule(test_three, 'test3', common_inputs_mod3)
})
}