Is there a more native way of remembering the last active tab, when changing tabsets (here in header / navbar), to return to it upon tabset change in bs4Dash
?
library(shiny)
library(bs4Dash)
library(shinyjs)
ui <- bs4DashPage(
header = bs4DashNavbar(
title = "Remember Last Tab in bs4Dash",
tags$div(
id = "tabset-container",
style = "display: flex; justify-content: center; gap: 10px; padding: 10px;",
div(
id = "tabset1",
style = "background-color: #0073B7; padding: 10px; color: white; cursor: pointer;", "Tab Set 1"
),
div(
id = "tabset2",
style = "background-color: #0073b7; padding: 10px; color: white; cursor: pointer;", "Tab Set 2"
)
)
),
sidebar = bs4DashSidebar(
uiOutput("sidebar_menu")
),
body = bs4DashBody(
useShinyjs(),
tags$script(HTML("
$(document).on('shiny:connected', function (event) {
Shiny.setInputValue('activeTabSet', 'tabset1')
})
Shiny.addCustomMessageHandler('selectTab', function(tabName) {
var sidebar = document.querySelector('[data-widget=\"treeview\"]');
var tab = sidebar.querySelector('[data-value=\"' + tabName + '\"]');
if (tab) tab.click();
});
Shiny.addCustomMessageHandler('tabsetReady', function(tabset) {
setTimeout(function() {
Shiny.setInputValue('tabsetReady', tabset, {priority: 'event'});
}, 100);
});
")),
bs4TabItems(
bs4TabItem(tabName = "tab1_1", h2("Content for Tab 1.1")),
bs4TabItem(tabName = "tab1_2", h2("Content for Tab 1.2")),
bs4TabItem(tabName = "tab2_1", h2("Content for Tab 2.1")),
bs4TabItem(tabName = "tab2_2", h2("Content for Tab 2.2"))
)
)
)
server <- function(input, output, session) {
# Reactive values to store the last visited tab for each tabset
lastTabs <- reactiveValues(tabset1 = "tab1_1", tabset2 = "tab2_1")
shinyjs::onclick("tabset1", {
runjs('Shiny.setInputValue("activeTabSet", "tabset1")')
})
shinyjs::onclick("tabset2", {
runjs('Shiny.setInputValue("activeTabSet", "tabset2")')
})
# Dynamically render the sidebar menu based on the active tabset
output$sidebar_menu <- renderUI({
req(input$activeTabSet)
if (input$activeTabSet == "tabset1") {
bs4SidebarMenu(
id = "sidebar",
bs4SidebarMenuItem("Tab 1.1", tabName = "tab1_1", icon = icon("dashboard")),
bs4SidebarMenuItem("Tab 1.2", tabName = "tab1_2", icon = icon("chart-bar"))
)
} else if (input$activeTabSet == "tabset2") {
bs4SidebarMenu(
id = "sidebar",
bs4SidebarMenuItem("Tab 2.1", tabName = "tab2_1", icon = icon("globe")),
bs4SidebarMenuItem("Tab 2.2", tabName = "tab2_2", icon = icon("cogs"))
)
}
})
observeEvent(input$sidebar, {
req(input$activeTabSet)
if (input$activeTabSet == "tabset1") {
lastTabs$tabset1 <- input$sidebar
} else if (input$activeTabSet == "tabset2") {
lastTabs$tabset2 <- input$sidebar
}
})
observeEvent(input$activeTabSet, {
req(input$activeTabSet)
session$sendCustomMessage("tabsetReady", input$activeTabSet)
})
observeEvent(input$tabsetReady, {
req(input$tabsetReady)
if (input$tabsetReady == "tabset1") {
session$sendCustomMessage("selectTab", lastTabs$tabset1)
} else if (input$tabsetReady == "tabset2") {
session$sendCustomMessage("selectTab", lastTabs$tabset2)
}
})
}
shinyApp(ui, server)
Answer in "more native way", without extra javascript
library(shiny)
library(bs4Dash)
ui <- bs4DashPage(
header = bs4DashNavbar(
title = "Remember Last Tab in bs4Dash",
tags$div(
id = "tabset-container",
style = "display: flex; justify-content: center; gap: 10px; padding: 10px;",
bs4Dash::actionButton("tabset1",
"Tab Set 1",
style = "background-color: #0073b7; padding: 10px; color: white; cursor: pointer;"
),
bs4Dash::actionButton("tabset2",
"Tab Set 2",
style = "background-color: #0073b7; padding: 10px; color: white; cursor: pointer;"
)
)
),
sidebar = bs4DashSidebar(
uiOutput("sidebar_menu")
),
body = bs4DashBody(
bs4TabItems(
bs4TabItem(tabName = "tab1_1", h2("Content for Tab 1.1")),
bs4TabItem(tabName = "tab1_2", h2("Content for Tab 1.2")),
bs4TabItem(tabName = "tab2_1", h2("Content for Tab 2.1")),
bs4TabItem(tabName = "tab2_2", h2("Content for Tab 2.2"))
)
)
)
server <- function(input, output, session) {
lastTabs <- reactiveValues(tabset1 = "tab1_1",
tabset2 = "tab2_1",
activeTabSet="tabset1"
)
updateTab.fct <- function (param_input, lastTabs_input) {
if (!(is.null(param_input)) && param_input >0 ) {
if (!is.null(lastTabs_input)) {
updatebs4TabItems(
session,
inputId = "sidebar",
selected =lastTabs_input[[lastTabs_input$activeTabSet]]
)
}
}
}
observeEvent(input$tabset1, {
lastTabs$activeTabSet <- "tabset1"
lastTabs$tabset1 <- lastTabs[[lastTabs$activeTabSet]]
updateTab.fct(input$tabset1,lastTabs)
}, ignoreInit = TRUE)
observeEvent(input$tabset2, {
lastTabs$activeTabSet <- "tabset2"
lastTabs$tabset2 <- lastTabs[[lastTabs$activeTabSet]]
updateTab.fct(input$tabset2,lastTabs)
}, ignoreInit = TRUE)
observeEvent(input$sidebar, {
if (is.null(input$sidebar) ) {
# lastTabs$activeTabSet <- "tabset1"
lastTabs$tabset1 <- lastTabs[[lastTabs$activeTabSet]]
updateTab.fct(1,lastTabs)
} else if (lastTabs$activeTabSet == "tabset1") {
lastTabs$tabset1 <- input$sidebar
} else if (lastTabs$activeTabSet == "tabset2") {
lastTabs$tabset2 <- input$sidebar
}
}, ignoreInit = FALSE, ignoreNULL = FALSE)
output$sidebar_menu <- renderUI({
if (ifelse (is.null(lastTabs$activeTabSet),"tabset1", lastTabs$activeTabSet) == "tabset1") {
bs4SidebarMenu(
id = "sidebar",
bs4SidebarMenuItem("Tab 1.1", tabName = "tab1_1", icon = icon("dashboard")),
bs4SidebarMenuItem("Tab 1.2", tabName = "tab1_2", icon = icon("chart-bar"))
)
} else {
bs4SidebarMenu(
id = "sidebar",
bs4SidebarMenuItem("Tab 2.1", tabName = "tab2_1", icon = icon("globe")),
bs4SidebarMenuItem("Tab 2.2", tabName = "tab2_2", icon = icon("cogs"))
)
}
})
}
shinyApp(ui, server)