Reputation: 10152
I have a largish shiny app, where multiple elements change reactiveVal
s. Now I want to port the app to use shiny modules to be able to test it more appropriately. But I am not able to access the reactive values that are defined inside the server function.
A simple app that highlights my thought process so far is this counter app.
The app consists two modules: counter
and display
counter
increases the reactive counter value on the click of a buttondisplay
watches the counter and displays its output to a text-fieldThe main part of the app is a "central" reactive value called counter_reactive
, which holds the current count.
This value is set by the counter
and read by the display
module elements.
library(shiny)
######################
# Counter Module
counter_UI <- function(id) {
ns <- NS(id)
tagList(
actionButton(ns("button"), "Increase Count")
)
}
counter <- function(input, output, session) {
observeEvent(input$button, {
counter_reactive(counter_reactive() + 1)
cat("Increase Counter by 1 to", counter_reactive(), "\n")
})
}
######################
# Display Module
display_UI <- function(id) {
ns <- NS(id)
tagList(
verbatimTextOutput(ns("text_output"))
)
}
display <- function(input, output, session) {
observe({
cat("Print Value of Counter\n")
output$text_output <- renderText(sprintf("Counter is now %i", counter_reactive()))
})
}
######################
# Rest of the Shiny App
ui <- fluidPage(
counter_UI("counter1"),
display_UI("display1")
)
server <- function(input, output, session) {
# Note that counter_reactive is defined inside the "global" server function,
# as multiple modules should read and write to it.
counter_reactive <- reactiveVal(0)
callModule(counter, "counter1")
callModule(display, "display1")
}
shinyApp(ui, server)
However, this app throws the error Warning: Error in counter_reactive: could not find function "counter_reactive"
.
Any ideas how to get/change the reactive value inside the module?
Upvotes: 0
Views: 448
Reputation: 10152
Rubber-Ducky-Debugging (aka SO-Question Writing Debugging) to the rescue, this works:
Simply passing the reactive value to the functions like so
counter <- function(input, output, session, counter_reactive) {
observeEvent(input$button, {
counter_reactive(counter_reactive() + 1)
cat("Increase Counter by 1 to", counter_reactive(), "\n")
})
}
display <- function(input, output, session, counter_reactive) {
observe({
cat("Print Value of Counter\n")
output$text_output <- renderText(sprintf("Counter is now %i", counter_reactive()))
})
}
server <- function(input, output, session) {
counter_reactive <- reactiveVal(0)
callModule(counter, "counter1", counter_reactive)
callModule(display, "display1", counter_reactive)
}
Upvotes: 1