Passing a Mixture of Reactive and Non-Reactives to a Shiny Module
Generally there is no issue in sending a list of parameters (reactive and non-reactive) to a shiny module. Here's an example where a shiny module would be called multiple times, programatically, where the reactive nature of the parameters may be variable (reactive in one instance but not in another). One way to deal with this is to read in the list of parameters and convert the non-reactive ones to reactive. Those originally reactive, remain so and therefore update on a change. In the examples below a single reactive or non-reactive list is passed from the parent shiny app to a shiny module. The concept works for a single or multiple inputs.
Example 1 - this shiny module will fail
This version of the shiny module fill fail - it expects a reactive but is passed a non-reactive.
1library(shiny)
2
3appmod_UI <- function(id) {
4 ns <- NS(id)
5 verbatimTextOutput(ns("txt"))
6}
7
8appmod <- function(input, output, session, inputlist) {
9
10 output$txt <- renderPrint({
11 message("Updating renderPrint")
12 print(inputlist()[["val1"]])
13 print(inputlist()[["val2"]])
14 })
15
16}
17
18ui <- fluidPage(
19 appmod_UI("mod1")
20)
21
22server <- function(input, output, session) {
23
24 callModule(appmod, "mod1", inputlist = list(val1 = "value 1", val2 = "value 2"))
25
26}
27
28shinyApp(ui, server)
Example 2 - reacive expected and reactive passed
This is a simple example of a shiny module that will work. It expects a reactive which is exactly what is passed to the module.
1library(shiny)
2
3appmod_UI <- function(id) {
4 ns <- NS(id)
5 verbatimTextOutput(ns("txt"))
6}
7
8appmod <- function(input, output, session, inputlist) {
9
10 message("Starting shiny module")
11
12 if (is.reactive(inputlist)) {
13 message("Returning inputlist")
14 inputlist_1 <- inputlist
15 } else {
16 message("Returning reactive inputlist")
17 inputlist_1 <- reactive(inputlist)
18 }
19
20 output$txt <- renderPrint({
21 message("Updating renderPrint")
22 print(inputlist_1()[["val1"]])
23 print(inputlist_1()[["val2"]])
24 })
25
26}
27
28ui <- fluidPage(
29 appmod_UI("mod1")
30)
31
32server <- function(input, output, session) {
33
34 callModule(appmod, "mod1", inputlist = reactive(list(val1 = "value 1", val2 = "value 2")))
35
36}
37
38shinyApp(ui, server)
39
Example 3 - reacive expected and non-reactive passed
Another example of a shiny module that will work. In this case the non-reactive passed to the shiny module is converted into a reactive.
1library(shiny)
2
3appmod_UI <- function(id) {
4 ns <- NS(id)
5 verbatimTextOutput(ns("txt"))
6}
7
8appmod <- function(input, output, session, inputlist) {
9
10 message("Starting shiny module")
11
12 if (is.reactive(inputlist)) {
13 message("Returning inputlist")
14 inputlist_1 <- inputlist
15 } else {
16 message("Returning reactive inputlist")
17 inputlist_1 <- reactive(inputlist)
18 }
19
20 output$txt <- renderPrint({
21 message("Updating renderPrint")
22 print(inputlist_1()[["val1"]])
23 print(inputlist_1()[["val2"]])
24 })
25}
26
27ui <- fluidPage(
28 appmod_UI("mod1")
29)
30
31server <- function(input, output, session) {
32
33 callModule(appmod, "mod1", inputlist = list(val1 = "value 1", val2 = "value 2"))
34
35}
36
37shinyApp(ui, server)
38
Example 4 - reacive expected and non-reactive passed
Final example of a shiny module that will work. In this case a reactive is passed and then changed (forcing an update in the shiny module).
1library(shiny)
2
3appmod_UI <- function(id) {
4 ns <- NS(id)
5 verbatimTextOutput(ns("txt"))
6}
7
8appmod <- function(input, output, session, inputlist) {
9
10 message("Starting shiny module")
11
12 if (is.reactive(inputlist)) {
13 message("Returning inputlist")
14 inputlist_1 <- inputlist
15 } else {
16 message("Returning reactive inputlist")
17 inputlist_1 <- reactive(inputlist)
18 }
19
20 output$txt <- renderPrint({
21 message("Updating renderPrint")
22 print(inputlist_1()[["val1"]])
23 print(inputlist_1()[["val2"]])
24 })
25
26
27}
28
29ui <- fluidPage(
30 appmod_UI("mod1"),
31 actionButton("but_update", "Update Values")
32)
33
34server <- function(input, output, session) {
35
36 rv <- reactiveValues(
37 i = list()
38 )
39
40 observe({
41 message("Define initial values")
42 rv$i <- list(val1 = "value 1", val2 = "value 2")
43 })
44
45 callModule(appmod, "mod1", inputlist = reactive(rv$i))
46
47 observeEvent(input$but_update, {
48 message("Button press")
49 rv$i[["val1"]] <- "value 3"
50 })
51
52}
53
54shinyApp(ui, server)
55