Problem
I have one module in my shiny app that resides in the R directory. Without modularizing, the app.R does not throw any errors. But with the module I get this error:
Error: Navigation containers expect a collection of `bslib::nav_panel()`/`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.
Code
app.R
library(shiny)
library(shinyWidgets)
library(bslib)
# Names
name_inputs <- layout_columns(
textInput(
inputId = "iname",
label = "Name of Instructor:",
value = ""
),
textInput(
inputId = "pname1",
label = "Name1:",
value = ""
),
textInput(
inputId = "pname2",
label = "Name2:",
value = ""
),
col_widths = c(4, 4, 4)
)
# UI
ui <- page_fluid(
tags$head(
tags$style(HTML("
.btn-group-label {
display: flex;
align-items: center;
flex-wrap: wrap;
}
.label-spacing {
margin-right: 10px;
min-width: 150px;
display: inline-block;
}"))
),
name_inputs,
mod_part_A_ui("part_A")
)
# Server
server <- function(input, output, session) {
mod_part_A_server("part_A")
}
shinyApp(ui, server)
Module
mod_part_A_ui <- function(id) {
ns <- NS(id)
tagList(
actionButton(ns("add"), "New"),
br(),
br(),
tabsetPanel(ns("tabs"))
)
}
mod_part_A_server <- function(id) {
moduleServer(
id,
function(input, output, session) {
ns <- session$ns
observeEvent(input$add, {
showModal(
modalDialog(
textInput(
inputId = ns("e_name"),
label = "E name:",
value = ""
),
actionButton(ns("submit_e_name"), "Submit"),
title = "Enter e name",
footer = NULL,
size = "s",
easyClose = FALSE
)
)
})
observeEvent(input$submit_e_name, {
removeModal()
e_name <- input$e_name
insertTab(inputId = "tabs",
tabPanel(
title = e_name,
tagList(
br(),
layout_columns(
tagList(
lapply(
c("F", "H", "T",
"R", "E", "A", "C",
"A", "C"),
function(x) {
div(
class = "btn-group-label",
span(class = "label-spacing", paste0(x, ":")),
radioGroupButtons(
inputId = ns(paste0("A_", gsub("\\s", "", x))),
choiceNames = c("+", "-", "x"),
choiceValues = c("p and p",
"p and n",
"not p"),
status = "primary",
size = "normal",
selected = character(0)
)
)
}
)
),
textAreaInput(inputId = ns("A_comments"),
label = "Notes:",
placeholder = "Add your notes here.",
width = "600px", height = "500px"),
col_widths = c(4, 8)
),
actionButton(ns("save"), "Save")
)
)
)
})
}
)
}
Traceback
The error traceback:
30.
stop(msg, call. = FALSE)
29.
FUN(X[[i]], ...)
28.
lapply(seq_len(length(tabs)), buildTabItem, tabsetId = tabsetId,
foundSelected = foundSelected, tabs = tabs, textFilter = textFilter)
27.
buildTabset(..., ulClass = paste0("nav nav-", type), id = id,
selected = selected)
26.
tabsetPanel_(..., type = "tabs", id = id, selected = selected,
header = header, footer = footer)
25.
new(...)
24.
func(..., id = id, selected = selected, header = header, footer = footer)
23.
remove_first_class(func(..., id = id, selected = selected, header = header,
footer = footer))
22.
tabsetPanel(ns("tabs"))
21.
dots_list(...)
20.
tagList(actionButton(ns("add"), "New"), br(), br(), tabsetPanel(ns("tabs"))) at mod_part_A.R#3
19.
mod_part_A_ui("part_A")
18.
dots_list(...)
17.
div(class = "container-fluid", ...)
16.
list2(...)
15.
bootstrapPage(div(class = "container-fluid", ...), title = title,
theme = theme, lang = lang)
14.
shiny::fluidPage(..., title = title, theme = theme, lang = lang,
if (isTRUE(theme_version(theme) >= 5)) component_dependencies())
13.
as_page(shiny::fluidPage(..., title = title, theme = theme, lang = lang,
if (isTRUE(theme_version(theme) >= 5)) component_dependencies()),
theme = theme)
12.
page_fluid(tags$head(tags$style(HTML("\n .btn-group-label {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n }\n .label-spacing {\n margin-right: 10px;\n min-width: 150px;\n display: inline-block;\n }"))),
name_inputs, mod_part_A_ui("part_A"))
11.
..stacktraceon..({
library(shiny)
library(shinyWidgets)
library(bslib) ...
10.
eval(exprs, envir)
9.
eval(exprs, envir)
8.
sourceUTF8(fullpath, envir = new.env(parent = sharedEnv))
7.
func(fname, ...)
6.
appObj()
5.
shinyAppDir_appR("app.R", appDir, options = options)
4.
shinyAppDir(x)
3.
as.shiny.appobj.character(appDir)
2.
as.shiny.appobj(appDir)
1.
runApp("for_help")
I am unable to identify what component needs to be wrapped in header and/or footer in the tabsetPanel. Please guide me what I'm missing.
Let's first look at the docs:
?tabsetPanel. Under the Usage section we see:The first parameter to
tabsetPanel()is...and notid.As such, when you pass the
idby position as the first argument, it goes in as.... Since...expecttabPanel()elements, the error you see is thrown.The solution is to pass
idas a named argument totabsetPanel():