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.
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)
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")
)
)
)
})
}
)
}
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:
tabsetPanel(
...,
id = NULL,
selected = NULL,
type = c("tabs", "pills", "hidden"),
header = NULL,
footer = NULL
)
The first parameter to tabsetPanel()
is ...
and not id
.
As such, when you pass the id
by position as the first argument, it goes in as ...
. Since ...
expect tabPanel()
elements, the error you see is thrown.
The solution is to pass id
as a named argument to tabsetPanel()
:
tabsetPanel(id = ns("tabs"))