I try to develop an R shiny app that renders n tabs. n should be hard coded in the server function and not be modified by the user. From these n rendered tabs, initially only the first tab should be displayed and all the others should be hidden. Each tab should includes a button that should switch to the next tab until n is reached. Very greatful for any hints
Here is the last test which did not run:
library(shiny)
library(shinyjs)
ui <- fluidPage(
mainPanel(
uiOutput("tabs")
)
)
server <- function(input, output) {
num_tabs <- 5 # Define the number of tabs
output$tabs <- renderUI({
tabs <- lapply(1:num_tabs, function(i) {
tabPanel(
paste("Tab", i),
actionButton(inputId = paste0("switch_tab_", i), label = "Switch Tab")
)
})
tabsetPanel(
id = "tabs_content",
do.call(tabPanel, c(tabs, id = paste0("tab_", 1:num_tabs)))
)
})
observe({
for (i in 2:num_tabs) {
runjs(paste("$('.nav-tabs li:nth-child(", i, ")').hide();"))
runjs(paste("$('.tab-content .tab-pane:nth-child(", i, ")').hide();"))
}
})
#
observeEvent({
lapply(1:num_tabs, function(i) {
input[[paste0("switch_tab_", i)]]
})
}, {
current_tab <- isolate({
tab_selected <- i
as.numeric(tab_selected)
})
if (!is.na(current_tab) && current_tab < num_tabs) {
next_tab <- current_tab + 1
runjs(paste("$('.nav-tabs li:nth-child(", next_tab, ")').show();"))
runjs(paste("$('.tab-content .tab-pane:nth-child(", next_tab, ")').show();"))
}
})
}
shinyApp(ui, server)
You have multiple issues. First, you need to have useShinyjs()
in the ui
. Next, all five tabs were not even created, as tabsetPanel
does not accept lists
(named tabs in your case). Next, use updateTabsetPanel
to switch tabs; you need session
in the server function for that. I also added a previous tab, in case you wish to go back to previous tab. Try this
library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
mainPanel(
uiOutput("tabs")
)
)
server <- function(input, output, session) {
num_tabs <- 5 # Define the number of tabs
### create 5 tabs
output$tabs <- renderUI({
do.call(tabsetPanel, c(id="tabs_content",
lapply(1:num_tabs, function(i) {
tabPanel(title = paste("Tab", i), value = paste0("tab_", i),
if (i>1) actionButton(inputId = paste0("prev_tab_", i), label = paste("Previous Tab")),
if (i<5) actionButton(inputId = paste0("switch_tab_", i), label = paste("Next Tab"))
)
})
))
})
### Initially, hide tabs 2 thru 5
observeEvent(input$tabs_content, {
for (i in 2:num_tabs) {
runjs(paste("$('.nav-tabs li:nth-child(", i, ")').hide();"))
#runjs(paste("$('.tab-content .tab-pane:nth-child(", i, ")').hide();"))
}
}, once = TRUE)
### upon clicking on the actionButton, open the next tab
lapply(1:(num_tabs-1), function(i) {
observeEvent(input[[paste0("switch_tab_", i)]], {
next_tab <- i+1
runjs(paste("$('.nav-tabs li:nth-child(", next_tab, ")').show();"))
updateTabsetPanel(session, "tabs_content", selected=paste0("tab_",next_tab) )
runjs(paste("$('.nav-tabs li:nth-child(", i, ")').hide();"))
#runjs(paste("$('.tab-content .tab-pane:nth-child(", next_tab, ")').show();"))
}, ignoreInit = TRUE, ignoreNULL = TRUE)
})
lapply(2:num_tabs, function(i) {
observeEvent(input[[paste0("prev_tab_", i)]], {
prev_tab <- i-1
runjs(paste("$('.nav-tabs li:nth-child(", prev_tab, ")').show();"))
updateTabsetPanel(session, "tabs_content", selected=paste0("tab_",prev_tab) )
runjs(paste("$('.nav-tabs li:nth-child(", i, ")').hide();"))
}, ignoreInit = TRUE, ignoreNULL = TRUE)
})
}
shinyApp(ui, server)