Hello, I'm trying to dynamically render output based on the input selected by the user. I can dynamically render the module UI and output but the module output is not being placed inside the module UI.
A simplified example using nyc flights is, for each origin selected, I want to generate a shiny box that contains a data table with all of the flights for that origin. My module UI creates the box UI and the output renders the datatable. When it renders the data table is rendered outside the box, as thought the UI is not connected to the output. I must be having some sort of namespace issue or naming issue.
library(shiny)
library(shinydashboard)
library(shinyWidgets)
library(shinyjs)
library(shinycssloaders)
library(nycflights13)
library(tidyverse)
nyc_flight_data <- nycflights13::flights
summaryTableUI <- function(id, title, width = 6, height="300px") {
ns <- NS(id)
box(title = title,
collapsible = TRUE, width = width,
DT::dataTableOutput(ns("summaryTable"), height = height) %>% withSpinner()
)
}
summaryTable <- function(input, output, session, data, run_click, origin_str) {
ns <- session$ns
output$dataTable <- DT::renderDataTable({
req(run_click())
data
}, options = list(scrollX = TRUE,
autoWidth = TRUE#, #Add a way to submit column defs
#columnDefs=column_defs_cfr
),
escape = FALSE)
}
ui <- dashboardPage(skin = "black",
dashboardHeader(
title="Test App"
),
dashboardSidebar(
sidebarMenu(id = "sidebar",
pickerInput(
inputId = "selectOrigin",
label = "Origin :",
choices = unique(nyc_flight_data$origin),
options = list(
`actions-box` = TRUE,
`live-search` = TRUE,
`virtual-scroll` = 10,
`multiple-separator` = "\n",
size = 10
),
multiple = TRUE
),
actionButton("runButton", "Run")
)
),
dashboardBody(
uiOutput("origin_flight_detail")
)
)
server <- function(input, output, session) {
click <- reactive(input$runButton)
output$origin_flight_detail <- renderUI({
req(input$runButton)
origin_list <- input$selectOrigin
unique_outputs <- length(origin_list)
lapply(1:unique_outputs, function(i) {
input_name <- paste0("input", i)
input_title <- origin_list[i]
print(paste0("input name: ",input_name))
#output_list[[i]]<- list(salesSummaryTableUI(ns(input_name),input_title))
list(summaryTableUI(input_name,input_title),
output[[input_name]] <- callModule(summaryTable,input_name,nyc_flight_data,click,origin_list[i]))
})
})
}
shinyApp(ui = ui, server = server)
If I skip the module UI call and just put the box around the callModule it works but that doesn't follow the standard module setup. Maybe that's OK? Hoping I'm just overlooking something simple. Thanks in advance for thoughts!
output$sales_detail <- renderUI({
req(run_click())
key_account_list <- inputs$key_account_list
unique_outputs <- length(key_account_list)
lapply(1:unique_outputs, function(i) {
input_name <- paste0("input", i)
# box(title = input_name,
# collapsible = TRUE, width = 6,
callModule(salesSummaryTable,input_name,sales_data,run_click,key_account_list[i])#)
})
})