In my shinydashboard app, I want to specify a different tabName in the sidebarMenu from the tabName in the body. The server function should then catch the tabName on click and call updateTabItems.
The idea is, that some menu items in the sidebar should go to the same tab, and the longer tabName in the sideBar contains additional information used to fill the tab.
When both tabNames in sideBar and tabItems are the same, the code works. However, if I change the tabName in the sideBar, e.g. to one_param_val, updateTabItems stops working.
Any ideas why that is and what I can do about it?
library(shiny)
library(shinydashboard)
ui <- shinydashboardPlus::dashboardPage(
header=shinydashboard::dashboardHeader(title = "Switch tabs"),
sidebar=shinydashboard::dashboardSidebar(
shinydashboard::sidebarMenu(id = "tabs",
shinydashboard::menuItem(
"Menu Item 1", tabName = "one_param_val" # works for tabName="one"
),
shinydashboard::menuItem(
"Menu Item 2", tabName = "two"
)
)
),
body=shinydashboard::dashboardBody(
shinydashboard::tabItems(
shinydashboard::tabItem(
tabName = "one", h2("Content One")
),
shinydashboard::tabItem(
tabName = "two", h2("Content Two")
)
)
)
)
server <- function(input, output, session) {
shiny::observeEvent(input$tabs, {
if(grepl("^one", input$tabs)) {
message("switching to one")
shinydashboard::updateTabItems(
session, inputId="tabs", selected="one"
)
}
})
}
shinyApp(ui, server)
Here is a workaround using a hidden menuItem. However the proxy menuItem will no longer get marked as selected in the sidebar:
library(shiny)
library(shinyjs)
library(shinydashboard)
ui <- shinydashboardPlus::dashboardPage(
header=shinydashboard::dashboardHeader(title = "Switch tabs"),
sidebar=shinydashboard::dashboardSidebar(
shinydashboard::sidebarMenu(id = "tabs",
shinyjs::hidden(shinydashboard::menuItem(
"Menu Item 1", tabName = "one"
)),
shinydashboard::menuItem(
"Menu Item 1", tabName = "one_param_val"
),
shinydashboard::menuItem(
"Menu Item 2", tabName = "two"
)
)
),
body=shinydashboard::dashboardBody(
useShinyjs(),
shinydashboard::tabItems(
shinydashboard::tabItem(
tabName = "one", h2("Content One")
),
shinydashboard::tabItem(
tabName = "two", h2("Content Two")
)
)
)
)
server <- function(input, output, session) {
shiny::observeEvent(input$tabs, {
# browser()
if(grepl("^one", input$tabs)) {
message("switching to one")
shinydashboard::updateTabItems(
session, inputId="tabs", selected="one"
)
}
})
}
shinyApp(ui, server)
Related
I want to hide and show a menuItem when a user check a box. I used useShinyjs() and renderMenu() function but once the menuItem is shown, I cannot hide it again by unchecking the box.
This is what I did :
library(shiny)
library(shinydashboard)
library(shinyjs)
header <- dashboardHeader(title = "my app")
sidebar <- dashboardSidebar(
sidebarMenu(id="menu",
menuItem("Tab 1",tabName = "tab1", icon = icon("question")),
menuItemOutput("another_tab"),
menuItem("Tab 2", tabName = "tab2", icon = icon("home"))
)
)
)
body <- dashboardBody(
tabItems(
tabItem(tabName = "tab1",
useShinyjs(),
checkboxInput("somevalue", "Check me", FALSE)
)
)
)
ui <- dashboardPage(header, sidebar, body)
server <- function(input, output) {
output$another_tab <- renderMenu({
if(input$somevalue == TRUE)
menuItem("My tab", tabName = "tab3", icon = icon("cogs"))
})
}
shinyApp(ui, server)
How can we hide the menuItem again ?
Another way to do it is
output$another_tab <- renderMenu({
if(input$somevalue == TRUE) {
menuItem("My tab", tabName = "tab3", icon = icon("cogs"))
}else shinyjs::hide(selector = "a[data-value='tab3']" )
})
You can create an empty menuItem():
server <- function(input, output) {
output$another_tab <- renderMenu({
if(input$somevalue == TRUE)
menuItem("My tab", tabName = "tab3", id="tab3", icon = icon("cogs"))
else
menuItem(NULL)
})
}
I am trying to have an action button within the Body of a tab (called "Widgets" in code) link to a different tab (called "data_table" in code). I know how to do this if the tab that I want to connect to, "data_table", is one of the menuItems that appears on the sidebarMenu. However, I do not wish for a link to the "data_table" tab to appear in the sidebar. I am stuck. I would have thought I need an "observeEvent"-type command which links the action button to the "data_table" tab. But I don't know what that is. Advice welcome. The code shows the UI side of things.
ui <- dashboardPage(
dashboardHeader(title = "My query"),
dashboardSidebar(
sidebarMenu(
menuItem("Dashboard", tabName = "dashboard", icon = icon("dashboard")),
menuItem("Widgets", tabName = "widgets", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")),
tabItem(tabName = "widgets",
h2("Widgets"),
actionButton(inputId="seedata", label = "See data")),
tabItem(tabName = "data_table",
h2("Table with the data"))
)
)
)
server <- function(input, output, session) { }
shinyApp(ui, server)
Perhaps you are looking for something like this.
ui <- dashboardPage(
dashboardHeader(title = "My query"),
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", tabName = "widgets", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "dashboard",
h2("Dashboard tab content")),
tabItem(tabName = "widgets", h2("Widgets"),
fluidRow(
tabBox(id = "tabset1", height = "850px", width=12, title = "My Data",
### The id lets us use input$tabset1 on the server to find the current tab
tabPanel("Table with the data", value="tab1", " ",
actionButton(inputId="seedata", label = "See data"),
uiOutput("dataTable")
),
tabPanel("Display Data Table", value="tab2", " ",
#uiOutput("someoutput")
DT::dataTableOutput("testtable")
)
)
)
))
)
)
server <- function(input, output, session) {
output$dataTable <- renderUI({
tagList(
div(style="display: block; height: 350px; width: 5px;",HTML("<br>")),
actionBttn(inputId="datatable",
label="Data Table",
style = "simple",
color = "success",
size = "md",
block = FALSE,
no_outline = TRUE
))
})
observeEvent(input$datatable, {
updateTabItems(session, "tabs", "widgets")
if (input$datatable == 0){
return()
}else{
## perform other tasks if necessary
output$testtable <- DT::renderDataTable(
mtcars,
class = "display nowrap compact", # style
filter = "top", # location of column filters
options = list( # options
scrollX = TRUE # allow user to scroll wide tables horizontally
)
)
}
})
observeEvent(input$datatable, {
updateTabsetPanel(session, "tabset1",
selected = "tab2")
})
}
shinyApp(ui, server)
I am building an app using the bs4Dash package, and I would like to include action buttons in the main page that would allow the user to jump to the appropriate page. However, the buttons do not do anything.
This is very much the same as this question. I believe the issue here is that updatebs4TabItems requires a TabSetPanel inputId... Except that I do not wish to include tabset panels here.
library(shiny)
library(bs4Dash)
ui <- bs4DashPage(
# Sidebar -------------------------------------------------------------
sidebar = bs4DashSidebar(
bs4SidebarMenu(
bs4SidebarMenuItem(
"Welcome",
tabName = "item0"
),
bs4SidebarMenuItem(
"Page 1",
tabName = "item1"
),
bs4SidebarMenuItem(
"Page 2",
tabName = "item2"
)
)
),
# Body -------------------------------------------------------------
body = bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "item0",
fluidRow(
actionButton("JumpToV1", "Go to Page 1"),
actionButton("JumpToV2", "Go to Page 2")
)
),
bs4TabItem(
tabName = "item1",
fluidRow(
bs4Callout(
title = "This is Page 1",
elevation = 4,
status = "danger"
)
)
),
bs4TabItem(
tabName = "item2",
fluidRow(
bs4Callout(
title = "This is Page 2",
elevation = 4,
status = "danger")
)
)
)
)
)
server <- function(input, output, session) {
observeEvent(input$JumpToV1, {
updatebs4TabItems(session, "item0", selected = "item1")
})
observeEvent(input$JumpToV2, {
updatebs4TabItems(session, "item0", selected = "item2")
})
}
shinyApp(ui, server)
You're close! Two things need adjusting. From the documentation, note that the selected argument in updatebs4TabItems takes an integer (the position of the selected tab), not a string (so not the id name you have). Also, the inputID argument for updatebs4TabItems will refer to the sidebarID for you, which you need to set. The below code should work how you want.
library(shiny)
library(bs4Dash)
ui <- bs4DashPage(
# Sidebar -------------------------------------------------------------
sidebar = bs4DashSidebar(
bs4SidebarMenu(
id = "sidebarID", #note the new ID here
bs4SidebarMenuItem(
"Welcome",
tabName = "item0"
),
bs4SidebarMenuItem(
"Page 1",
tabName = "item1"
),
bs4SidebarMenuItem(
"Page 2",
tabName = "item2"
)
)
),
# Body -------------------------------------------------------------
body = bs4DashBody(
bs4TabItems(
bs4TabItem(
tabName = "item0",
fluidRow(
actionButton("JumpToV1", "Go to Page 1"),
actionButton("JumpToV2", "Go to Page 2")
)
),
bs4TabItem(
tabName = "item1",
fluidRow(
bs4Callout(
title = "This is Page 1",
elevation = 4,
status = "danger"
)
)
),
bs4TabItem(
tabName = "item2",
fluidRow(
bs4Callout(
title = "This is Page 2",
elevation = 4,
status = "danger")
)
)
)
)
)
server <- function(input, output, session) {
observeEvent(input$JumpToV1, {
#changed ID and selected here and below
updatebs4TabItems(session, inputId = "sidebarID", selected = 2)
})
observeEvent(input$JumpToV2, {
updatebs4TabItems(session, inputId = "sidebarID", selected = 3)
})
}
shinyApp(ui, server)
In the example below, there are two menuItems (1 and 2) and a menuSubItem (2.1) thats nested within menuItem 2. Each menuItem has a corresponding tabItem with a box, where the boxtitle is the name of the menuItem. If i run this app "Menu 1" is initally selected and shows the box called "1". If i than click on "Menu 2" the menuSubItem expands, but the body does not change at all.
I don't think that this is the normal behaviour, is there a way to fix this?
And a second question. If I have selected "Menu 2.1" and click on "Menu 1" why does the nested menuItem do not collapse again?
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(disable=TRUE),
dashboardSidebar(
sidebarMenu(
menuItem(
"Menu 1",
tabName="menu1"
),
menuItem(
"Menu 2",
tabName = "menu2",
menuSubItem(
"Menu 2.1",
tabName = "menu2_1"
)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName="menu1",
box("1")
),
tabItem(tabName="menu2",
box("2")
),
tabItem(tabName="menu2_1",
box("2.1")
)
)
)
)
server <- function(input, output) {
}
shinyApp(ui = ui, server = server)
The behaviour you see is normal, see here
Childless menuItem()s/menuSubItem()s must be given a tabName argument
Childfull” menuItem()s cannot have a tabName or a selected argument
(or rather, they can, but this will be completely ignored by Shiny).
Instead, at most, one of them can take a startExpanded = TRUE, which
tells Shiny to start out with that menuItem() expanded, i.e. revealing
all its children
You can access the expanded tab with my code below, so you can create behavior based on that, but I do not think it is possible to display a page when clicking a menuItem that has children.
Hope this helps!
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(disable=TRUE),
dashboardSidebar(
sidebarMenu(
menuItem(
"Menu 1",
tabName="menu1"
),
menuItem(
"Menu 2",
expandedName = "menu2",
menuItem(
"Menu 2.1",
tabName = "menu2_1"
)
)
),
textOutput('selectedmenu')
),
dashboardBody(
tabItems(
tabItem(tabName="menu1",
box("1")
),
tabItem(tabName="menu2",
box("2")
),
tabItem(tabName="menu2_1",
box("2.1")
)
)
)
)
server <- function(input, output) {
output$selectedmenu <- renderText({
print(input$sidebarItemExpanded)
})
}
shinyApp(ui = ui, server = server)
Change first tab when menu 2 is expanded, request from comment:
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(disable=TRUE),
dashboardSidebar(
sidebarMenu(id="mysidebar",
menuItem(
"Menu 1",
tabName="menu1"
),
menuItem(
"Menu 2",
expandedName = "menu2",
menuItem(
"Menu 2.1",
tabName = "menu2_1"
)
)
)
),
dashboardBody(
tabItems(
tabItem(tabName="menu1",
box("1")
),
tabItem(tabName="menu2",
box("2")
),
tabItem(tabName="menu2_1",
box("2.1")
)
)
)
)
server <- function(input, output,session) {
observeEvent(input$sidebarItemExpanded, {
updateTabItems(session,"mysidebar","menu2_1")
})
}
shinyApp(ui = ui, server = server)
(cross post from shiny google groups, https://groups.google.com/forum/#!topic/shiny-discuss/CvoABQQoZeE)
How can one navigate to a particular sidebar menu item in ShinyDashboard?
sidebarMenu(
menuItem("Menu Item 1")
menuItem("Menu Item 2")
)
i.e. how can I put a button on the "Menu Item 1" page that will link to "Menu Item 2"?
To navigate between tabs I am using the updateTabsetPanel function:
observeEvent(input$go,{
updateTabsetPanel(session, "tabset1", selected = "Step 2")
})
I believe I should be able to use a similar function to navigate to a sidebar menu, but I am not sure what that is.
Any pointers greatly appreciated
Thanks
Iain
Is this what you are looking for? note that the example is taken from Change the selected tab on the client
library(shiny)
library(shinydashboard)
ui <- dashboardPage(
dashboardHeader(title = "Simple tabs"),
dashboardSidebar(
sidebarMenu(id = "tabs",
menuItem("Menu Item 1", tabName = "one", icon = icon("dashboard")),
menuItem("Menu Item 1", tabName = "two", icon = icon("th"))
)
),
dashboardBody(
tabItems(
tabItem(tabName = "one",h2("Dashboard tab content"),actionButton('switchtab', 'Switch tab')),
tabItem(tabName = "two",h2("Widgets tab content"))
)
)
)
server <- function(input, output, session) {
observeEvent(input$switchtab, {
newtab <- switch(input$tabs, "one" = "two","two" = "one")
updateTabItems(session, "tabs", newtab)
})
}
shinyApp(ui, server)