Note 07/19/2023: I have updated my question. Earlier today I edited my question with the new information, but for readability purposes, I think it's reasonable to write this edit in a response. Hence, for the question's current state, see my response further down.
I am struggling with understanding how modules play together in Shiny. I believe a major part of this stems from me not understanding reactivity properly, but I've tried various different things and the best that's happened so far was that the error I got changed.
My use case is a modularized app where I try to get the following architecture to work:
- main script contains ui object and server function
- the ui object utilizes a modularized sidebarPanel containing various interactive elements
- the server maintains the selected language (best done via session$userData?) and calls three modules, these being:
- server function belonging to the modularized sidebarPanel:
- prepares input data and calls backend algorithm. Returns a list of dataframes to the main script for further processing from the main script
- makeDatatable function turning the list of data frames into some nicely formatted datatable. Before modularizing, this part of the code set output$datatableUI by calling renderUI on a tabsetPanel.
- makePlots function generating a tabsetPanel of plotOutput objects. This, too, previously set output$plotUI by calling renderUI on a tabsetPanel
What I struggle with most, I believe, is a lack of understanding what a reactive value truly is - if my backend code generates a data structure which should be updated in the main script any time there is a certain user interaction, is that saved value then a reactiveValues
? Do I need to save this as a reactiveValues
?
I have found this (Shiny Modules with Observes and reactiveValues) solution to a somewhat similar question from 2018, but from what I understand it is making use of a heavily deprecated UI which earlier I had been told to "let finally die". Anyways, here is my code. I would appreciate any kind of help.
# module.R
#-------------------------------------------------------------------------------
library(shiny)
modulePanel <- function(id) {
ns <- NS(id)
sidebarPanel(
# some user elements ...
radioButtons(
inputId = ns("lang"),
label = "Language",
choices = c("One", "Two")
)
)
}
modulePanelServer <- function(id) {
moduleServer(
id,
function(input, output, session) {
observe(
# observing some events... This should execute any time the value this is bound to changes, right?
) %>% bindEvent(ns("lang"))
reactive({
# When do I use this over observe? Another aspect that I am struggling with
}) %>% bindEvent(ns("lang"))
df <- data.frame(A=5, B=4, C="text")
# Option 1:
return(df)
# Option 2:
return(renderDataTable(df)) # but neither works
}
)
}
#-------------------------------------------------------------------------------
# main.R
#-------------------------------------------------------------------------------
source("module.R")
library(shiny)
ui <- navbarPage(
title = "some title",
modulePanel("panelId"),
mainPanel(
tabsetPanel(
tabPanel(title="Tab 1", uiOutput("module_out"))
# Target UI:
# tabPanel(title="Tab 2", uiOutput("datatableServerOutput")),
# tabPanel(title="Tab 3", uiOutput("plotServerOutput"))
)
)
)
server <- function(input, output, session) {
module_server_out <- modulePanelServer("panelId")
# Option 1:
# With this, I'm getting this error:
# Warning: Error in module_server_out: could not find function "module_server_out"
output$module_out <- module_server_out()
# Option 2:
# With this, I'm getting this error:
# Error in tempVarsPromiseDomain(outputInfoEnv, outputName = name, session = shinysession) :
# argument "name" is missing, with no default
output$module_out <- renderDataTable(module_server_out()) # ... but neither works
# Target SERVER:
# Something akin to this...
# inputServerOutput <- inputServer("inputServer")()
# output$datatableServerOutput <- datatableServer("datatableServer", inputServerOutput)()
# output$plotServerOutput <- plotServer("plotServer", inputServerOutput)()
}
shinyApp(ui, server)