Shinydashboard supports all the normal interactive functionality that Shiny does. If you need a refresher on all the interactive capabilities of Shiny (through inputs, outputs, reactives, etc), take a look at our website’s articles.
In addition to all the normal Shiny inputs and outputs that can be present in a shinydashboard app, there are a few things that are specific to the structure of such apps. In particular, most shinydashboard apps have a sidebar. As of the 0.6 shinydashboard release, app authors can access the entire state of the sidebar as Shiny inputs. There are up to three inputs that can be generated if you have a sidebar in your app. (However, it should be noted that two these are not “normal” inputs, since they are generated automatically and have a fixed name – rather than you, as the app author, deciding that name.)
Let’s get into the details. The three sidebar-related inputs allow you to:
If you want to know which tab is currently visible, you need to know which menu item is active. To do this, the sidebarMenu()
must have an id
, and the menuItem()
/menuSubItem()
must have a tabName
. In particular, if you pass in id = "tabs"
to your sidebarMenu()
, then you can know which sidebar item is selected by accessing the variable input$tabs
. The value associated with input$tabs
is given by the tabName
argument of the currently selected menuItem()
(or menuSubItem()
).
The screenshot below shows an app that indicates which menuItem()
is selected:
Here’s the code for the app pictured above. Notice that all childless menuItem()
s and menuSubItem()
s have a tabName
argument:
app.R
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets"),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
)
),
textOutput("res")
),
dashboardBody(
tabItems(
tabItem("dashboard", "Dashboard tab content"),
tabItem("widgets", "Widgets tab content"),
tabItem("subitem1", "Sub-item 1 tab content"),
tabItem("subitem2", "Sub-item 2 tab content")
)
)
)
server <- function(input, output, session) {
output$res <- renderText({
paste("You've selected:", input$tabs)
})
}
shinyApp(ui, server)
As mentioned, sidebarMenu()
must take in an id
. For example if you pass in id = "tabs"
, then, anywhere in the server function, you can know which menuItem()
(or menuSubItem()
) is selected by accessing input$tabs
. If you don’t pass in an id
, you won’t be able access to this information. In addition, you need to specify a tabName
for all “leaf” items (i.e. all menuItem()
s or menuSubItem()
s that don’t have any children), even if you wouldn’t need it otherwise. If you don’t specify a tabName
, then that item will not be clickable, though the the other items will continue to function as normal (i.e. not specifying a tabName
for an item is functionally the same as not having that item at all - except for the different visual look - since you won’t be able to interact with it at all).
This works exactly the same for dynamically generated sidebarMenu()
s. Here’s an identical-looking app, whose only difference is that the sidebar menu is generated dynamically:
app.R
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenuOutput("menu"),
textOutput("res")
),
dashboardBody(
tabItems(
tabItem("dashboard", "Dashboard tab content"),
tabItem("widgets", "Widgets tab content"),
tabItem("subitem1", "Sub-item 1 tab content"),
tabItem("subitem2", "Sub-item 2 tab content")
)
)
)
server <- function(input, output, session) {
output$res <- renderText({
paste("You've selected:", input$tabs)
})
output$menu <- renderMenu({
sidebarMenu(
# Setting id makes input$tabs give the tabName of currently-selected tab
id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets"),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
)
)
})
}
shinyApp(ui, server)
To bookmark which sidebar item is selected, the sidebarMenu()
needs to have an id
. For example, the app below does not specify any explicit inputs (like textInput
or sliderInput
), but the state of the sidebar is automatically bookmarked (you can see this in the URL once you click “Bookmark…”). The app below combines all three inputs described before. You can use it to experiment with:
menuItem()
/ menuSubItem()
(and see the value of input$tabs
also change);menuItem()
(and see the value of input$sidebarItemExpanded
also change);input$sidebarCollapsed
also change).app.R
library(shiny)
library(shinydashboard)
ui <- function(req) {
dashboardPage(
dashboardHeader(),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", icon = icon("th"), tabName = "widgets"),
menuItem("Charts", icon = icon("bar-chart-o"),
menuSubItem("Sub-item 1", tabName = "subitem1"),
menuSubItem("Sub-item 2", tabName = "subitem2")
)
)
),
dashboardBody(
bookmarkButton()
)
)
}
server <- function(input, output, session) {}
shinyApp(ui, server, enableBookmarking = "url")
For shinytest to be able to record and replay which menu item is selected, the sidebarMenu()
must have an id
, and the menuItem
s and menuSubItem
s must have have tabName
s.