2

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.
bretauv
  • 7,756
  • 2
  • 20
  • 57
Yao-Chung
  • 69
  • 4

1 Answers1

2

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)
bretauv
  • 7,756
  • 2
  • 20
  • 57
  • Thank you @bretauv. Now it works! I am wondering if there is a way to remove the id prefix set by `ns <- NS(id)`? I got **table1-mtcars table** following your code. – Yao-Chung Feb 21 '22 at 16:54
  • 1
    `ns("mtcars table")` appends the id of the module ("table1") to the name "mtcars table". Remove `ns()` if you want to display "mtcars table" – bretauv Feb 21 '22 at 20:19