I want to create a shiny app that uses navbarMenu()
and tabPanel()
to display data tables. Instead of writing all of the codes in one app.R
file, I plan to use the concept of shiny modules creating R/tabUI.R
and R/tabServer.R
to generate these tables.
However, I run into an error and cannot figure it out. Any suggestions and help are appreciated!
My code:
### R/tabUI.R
tabUI <- function(id) {
tagList(
navbarMenu("display table",
tabPanel(NS(id, "mtcars table"),
DT::dataTableOutput("table")
)
)
)
}
### R/tabServer.R
tabServer <- function(id) {
moduleServer(id, function(input, output, session){
output$table <- DT::renderDataTable(mtcars)
})
}
### app.R
library(shiny)
ui <- navbarPage("dashboard",
tabUI("table1")
)
server <- function(input, output, session){
tabServer("table1")
}
shinyApp(ui=ui, server=server)
Error:
> runApp()
Error: Navigation containers expect a collection of `bslib::nav()`/`shiny::tabPanel()`s and/or `bslib::nav_menu()`/`shiny::navbarMenu()`s. Consider using `header` or `footer` if you wish to place content above (or below) every panel's contents.
You can't use tagList()
inside navbarPage()
so you need to remove it from the module.
As a sidenote, you should define ns <- NS(id)
at the beginning of the module and then wrap all ids in ns()
. In your code, the table id was not wrapped in ns()
so it wasn't displayed.
Fixed code:
### R/tabUI.R
tabUI <- function(id) {
ns <- NS(id)
navbarMenu("display table",
tabPanel(ns("mtcars table"),
DT::dataTableOutput(ns("table"))
)
)
}
### R/tabServer.R
tabServer <- function(id) {
moduleServer(id, function(input, output, session){
output$table <- DT::renderDataTable(mtcars)
})
}
### app.R
library(shiny)
ui <- navbarPage("dashboard",
tabUI("table1")
)
server <- function(input, output, session){
tabServer("table1")
}
shinyApp(ui=ui, server=server)