I'm building a Shiny app using the great ShinyDashoardPlus
package (styled with a theme from the Dashboardthemes
package) that has three tabItems
holding the contents for the three sections of the app (section A, section B, and section C), accessible through the sidebarMenu
in the left dashboardSidebar
, and a right sidebar with two tabs (implemented as rightSidebarTabContent
with the following ids: T_A
and T_B
) holding controls to explore further the contents of sections A and B respectively.
Since the rightSidebarTabContent
T_A
is only relevant for section A
, and rightSidebarTabContent
T_B
is only relevant for section B
, I would like that (1) the user's click on the left sidebar menu items A or B could activate the corresponding tab in the right sidebar. Moreover, since none of the rightSidebarTabContents
is relevant in section C
, I'd also like that (2) the user's click on the on the left sidebar menu item C could close the rightsidebar, if it is open.
I've found a possible hint on how to solve my problems (Automatic rightSidebar popup when menuItem is clicked in shinydashboardPlus), and I was indeed able to partially solve my first problem adding/removing some CSS class via shinyjs
to activate a part of the different tabs in the rightSidebar
at click on the menuItems
.
As I said, this solution partially works for my first issue, although only the rightSidebarTabContent
lower part is activated/deactivated in this way, but not the tab header with the icons for navigating between them. Moreover, possibly due to extra CSS classes added when I apply the shinydashboard theme "dark", I'm not able to toggle the closing of the rightSidebar
at click on section C
menu item (issue # 2).
To summarize:
T_A
should expand when left sidebar item section A
is selected. Likewise for T_A
and section B
.section C
is selected on the left sidebarCan anyone please help with this? Thanks in advance for any help!
library(shiny)
library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
ui <- dashboardPagePlus(
useShinyjs(),
header = dashboardHeaderPlus(
title = "Dashboard",
enable_rightsidebar = TRUE,
rightSidebarIcon = "info-circle"
),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem("Section A", tabName = "Section_A", icon = icon("map")),
menuItem("Section B", tabName = "Section_B", icon = icon("chart-line")),
menuItem("Section C", tabName = "Section_C", icon = icon( "gears")),
id = "nav"
)
),
body = dashboardBody(
shinyDashboardThemes(
theme = "grey_dark"
),
tabItems(
tabItem(
tabName = "Section_A",
p("Some content for section A")),
tabItem(
tabName = "Section_B",
p("Some content for section B")),
tabItem(
tabName = "Section_C",
p("Some content for section C"))
)
),
rightsidebar = rightSidebar(
background = "dark",
rightSidebarTabContent(
id = "T_A",
title = "Tab for section A",
icon = "desktop",
active = TRUE,
p("Some content frelevant for section A"),
sliderInput(
"obs",
"Number of observations:",
min = 0, max = 1000, value = 500
)
),
rightSidebarTabContent(
id = "T_B",
title = "Tab for section B",
p("Some content frelevant for section B"),
textInput("caption", "Caption", "Data Summary")
)
),
title = "Right Sidebar"
)
server <- function(input, output) {
observe({
if (req(input$nav) == "Section_A"){
message("Section A has been selected")
shinyjs::removeClass(id = "control-sidebar-T_A-tab", class = "tab-pane")
shinyjs::removeClass(id = "control-sidebar-T_B-tab", class = "tab-pane active")
shinyjs::addClass(id = "control-sidebar-T_A-tab", class = "tab-pane active")
shinyjs::addClass(id = "control-sidebar-T_B-tab", class = "tab-pane")
}
if (req(input$nav) == "Section_B"){
message("Section B has been selected")
shinyjs::removeClass(id = "control-sidebar-T_B-tab", class = "tab-pane")
shinyjs::removeClass(id = "control-sidebar-T_A-tab", class = "tab-pane active")
shinyjs::addClass(id = "control-sidebar-T_B-tab", class = "tab-pane active")
shinyjs::addClass(id = "control-sidebar-T_A-tab", class = "tab-pane")
}
if (req(input$nav) == "Section_C"){
message("Section C has been selected")
shinyjs::removeClass(selector = "aside.control-sidebar-open aside.control-sidebar-dark", class = "control-sidebar-open aside.control-sidebar-dark-open")
shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar")
}
})
}
shinyApp(ui = ui, server = server)
You can render your right sidebar items reactively through renderUI
instead of modifying the CSS
. Inside rightSidebar
we can place a single uiOutput
that would get populated with different contents dependent on the chosen item in the left sidebar. Note that this is a partial solution. The sidebar, once expanded, will still not collapse when selecting section C
in the left sidebar. [See edit below that addresses collapsing of the right sidebar.]
library(shinyjs)
library(shinyWidgets)
library(shinydashboard)
library(shinydashboardPlus)
library(dashboardthemes)
ui <- dashboardPagePlus(
useShinyjs(),
header = dashboardHeaderPlus(
title = "Dashboard",
enable_rightsidebar = TRUE,
rightSidebarIcon = "info-circle"
),
sidebar = dashboardSidebar(
sidebarMenu(
menuItem("Section A", tabName = "Section_A", icon = icon("map")),
menuItem("Section B", tabName = "Section_B", icon = icon("chart-line")),
menuItem("Section C", tabName = "Section_C", icon = icon( "gears")),
id = "nav"
)
),
body = dashboardBody(
shinyDashboardThemes(
theme = "grey_dark"
),
tabItems(
tabItem(
tabName = "Section_A",
p("Some content for section A")),
tabItem(
tabName = "Section_B",
p("Some content for section B")),
tabItem(
tabName = "Section_C",
p("Some content for section C"))
)
),
rightsidebar = rightSidebar(
background = "dark",
uiOutput("side_bar"),
title = "Right Sidebar"
)
)
server <- function(input, output) {
observe({
if (req(input$nav) == "Section_A"){
message("Section A has been selected")
# added in edit
shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
output$side_bar <- renderUI({
rightSidebarTabContent(
id = "T_A",
title = "Tab for section A",
p("Some content relevant for section A"),
sliderInput(
"obs",
"Number of observations:",
min = 0, max = 1000, value = 500
)
)
})
}
if (req(input$nav) == "Section_B"){
message("Section B has been selected")
# added in edit
shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
output$side_bar <- renderUI({
rightSidebarTabContent(
id = "T_B",
title = "Tab for section B",
p("Some content relevant for section B"),
textInput("caption", "Caption", "Data Summary")
)
})
}
if (req(input$nav) == "Section_C"){
message("Section C has been selected")
# added in edit
shinyjs::removeClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
output$side_bar <- renderUI({ div() })
}
})
}
shinyApp(ui = ui, server = server)
Edit: Collapse the right sidebar when section C
is clicked. After reading the post you linked more carefully, you can simply add
shinyjs::addClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
in your observer when section A
and section B
are selected, and add
shinyjs::removeClass(selector = "aside.control-sidebar", class = "control-sidebar-open")
when section C
is selected.
Then the right sidebar will expand and collapse based on selections in the left sidebar.
A gif of the behavior:
Adding to teofil's answer, you can use selector = "body" instead so the right sidebar can still be opened and closed.
shinyjs::addClass(selector = "body", class = "control-sidebar-open")
shinyjs::removeClass(selector = "body", class = "control-sidebar-open")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With