(I read through this question and, despite the similar titles, it is not relevant to my problem—or, if it is, I'm too dumb to see how it applies.)
I'm working on modularizing my Shiny code so that adding additional graphs only requires the addition of a couple of functions in a separate file. There are three panels—a side-panel (wherein a user selects a graph), a bottom-panel (wherein a user selects graph-parameters), and a main panel (wherein the graph is displayed).
The side-panel doesn't change, but the bottom panel changes according to what's selected in the side-panel.
side_panel.R
# UI function
sidePanelInput <- function(id, label='side panel') { # Some input w/ ns = selected_graph }
# Server function
sidePanel <- function(input, output, session) {
selected_graph <- reactive({input$selected_graph})
return(selected_graph)
In my app.R file, selected_graph
gets passed to both the bottom panel and the main panel:
app.R
# ...
sidePanel <- callModule(sidePanel, 'side')
bottomPanel <- callModule(bottomPanel, 'bottom', data=some_data, selected_graph=sidePanel)
mainPanel <- callModule(mainPanel, "main", data=some_data, selected_graph=sidePanel, params=bottomPanel)
# ...
So far so good (notice that the bottomPanel
also return something, and that gets passed to mainPanel
). All of this passing back and forth works well. Here's my problem: The bottom panel for each graph is different, and defined in a separate file. This means that the bottomPanel
module needs to know what to render from the reactive that sidePanel
spits out. This also means that I don't use a UI function for bottomPanel
, I only use a server function w/ renderUI
:
bottom_panel.R
source('graphs')
bottomPanel <- function(input, output, session, data, selected_graph) {
# Call the function of the graph, depending on what the selected graph is
output$bottomPanel <- renderUI({
tagList(
match.fun(paste(selected_graph(), '_bottom_panel', sep=''))(session$ns('id'))
)
})
# So, if the selected graph is 'scatter_1', then the function call will be
# scatter_1_bottom_panel(session$ns('id')) -- An example of a bottom_panel function
# is provided at the end of this question, but it works as intended
# Now, we set the defaults (specific to the graph); for example, slider-ranges
# will be set according to mins and maxes in the data. Similar to above, a
# match.fun() call is used here to determine how the defaults are set
observe({
match.fun(paste(selected_graph(), '_bottom_panel_defaults', sep=''))(session, data)
})
# Here is my problem. I need to output the parameters of the newly-rendered
# bottom panel, so that those parameters can be passed to the main panel. This
# as it is doesn't work, because one apparently can't read from server output
params <- reactive({output$bottomPanel})
return(params)
}
How can I output the parameters of the rendered UI after it's rendered and the default-value function is called?
example_bottom_panel.R
scat_2_bottom_panel <- function(id) {
ns <- NS(id)
panel <- wellPanel(
sliderInput(
inputId = ns('duration_range'),
label = 'Duration of Sound [ms]',
min = 0,
max = 10000,
value = c(0, 10000),
step = 100,
round = FALSE,
ticks = TRUE
)
)
return(panel)
}
example_default_function.R
scatter_1_bottom_panel_defaults <- function(session, data) {
updateSliderInput(session, 'duration_range', value=c(min(data$duration), max(data$duration)))
}
I've read through the above-linked question a few times more, and it seems like this is what was done in the server function:
xvar <- reactive({input[[ "xvar" ]] })
yvar <- reactive({input[[ "yvar" ]] })
And then xvar
and yvar
were used as parameters in the renderUI
call. At first glance, this doesn't work for me; the reactive values necessary for each bottom panel change according to the graph that the user selected. Maybe I can include the renderUI call within the bottom_panel function, declare these IDs as reactive, and use them in the panel generation?