I am developing a Shiny application with nested shiny modules, when I define variable UI elements within a nested module server the parent module name space is not inherited correctly. For example, if you had the following
The UI when inspecting the application would display the name-spacing as 'parent-child-...' however when a UI element is defined from the child servers it is now only 'child-...'. To account for this I tried a hacky solution and it worked by pasting 'parent' in front of the 'child' id when creating the element.
I've created an example to capture this issue.
library(shiny)
# Base UI and server elements -------------------------------------------------
histogramUI <- function(id) {
ns <- NS(id)
tagList(
selectInput(ns("var"), "Variable", choices = names(mtcars)),
numericInput(ns("bins"), "bins", value = 10, min = 1),
plotOutput(ns("hist"))
)
}
histogramServer <- function(id) {
moduleServer(id, function(input, output, session) {
data <- reactive(mtcars[[input$var]])
output$hist <- renderPlot({
hist(data(), breaks = input$bins, main = input$var)
}, res = 96)
})
}
# Button UI and server elements ------------------------------------------------
buttonUI <- function(id) {
ns <- NS(id)
uiOutput(ns("new_btn"))
}
# Server created button
buttonServer <- function(id) {
moduleServer(id, function(input, output, session) {
observe({
req(input$var == "cyl")
output$new_btn <-
renderUI({
div(
actionButton(
# Does work \/\/\/
NS(paste0('test-', id), 'action_button'),
# Doesn't work \/\/\/
# NS(id, 'action_button')
label = "Button test")
)
})
})
observeEvent(input$action_button, {
# Printing the session id and selected var
print(id)
print(input$var)
})
})
}
# Master UI elements
major_piece_of_func_ui <- function(id){
ns <- NS(id)
div(
histogramUI(ns("hist_test_1")),
buttonUI (ns("hist_test_1"))
)
}
major_piece_of_func_serv <-
function(id) {
moduleServer(id, function(input, output, session) {
histogramServer("hist_test_1")
buttonServer ("hist_test_1")
})
}
# Ui and server construction
ui <- fluidPage(
major_piece_of_func_ui('test')
)
server <- function(input, output, session) {
major_piece_of_func_serv('test')
}
shinyApp(ui, server)
I am very open to the fact that I may be going about this in the completely wrong way and am open to alternative solutions that at a minimum hold the following constraints:
Constraints:
Cheers, Aidan
For a non-nested module, NS(id)
is equivalent to session$ns
in the server part. But not for a nested module. For a nested module, use session$ns
, it returns the namespacing function with the composed namespace.