My shiny app uses a reactable with nested detail tables using a shiny tabsetPanel. I've recreated the effect in the reprex below. What I expect is that when the user selects a different detail tab to display it replaces the current one. Instead, it stacks both the current tab and the selected tab on top of one another. I've experimented with using different values in the tabsetPanel's "selected = " argument (see the input control in the sidebar). The closet I've come to the expected behavior is to with "selected = ''", i.e., an empty string. However, that causes the app to initialize with no detail data displayed. At this point, I'm trying to understand if this is a bug or a function of the shiny tabsetPanel, the reactable details function, or both.
Thank if advance for any advice.
library(reactable)
library(tidyverse)
library(shiny)
library(shinydashboard)
#>
#> Attaching package: 'shinydashboard'
#> The following object is masked from 'package:graphics':
#>
#> box
main_table <- iris %>%
select(Species) %>%
unique()
nested1 <- iris %>%
select(Species, Sepal.Length)
nested2 <- iris %>%
select(Species, Sepal.Width)
nested3 <- iris %>%
select(Species, Petal.Length)
nested4 <- iris %>%
select(Species, Petal.Width)
ui <- dashboardPage(
dashboardHeader(title = "Nested Reactables"),
dashboardSidebar(
radioButtons(inputId = "selected_detail",
label = "Select default tabPanel",
choices = c("detail1",
"detail2",
"detail3",
"detail4",
"empty string")
)
),
dashboardBody(
reactableOutput("table")
)
)
server <- function(input, output, session) {
output$table <- renderReactable({
reactable(
data = main_table,
details = function(index) {
specie <- main_table$Species[[index]]
tabsetPanel(
selected = input$selected_detail,
type = c("tabs"),
tabPanel(
value = "detail1",
title = "Sepal Length",
reactable(
data = filter(nested1, Species == specie) %>% select(-Species),
fullWidth = FALSE
)
),
tabPanel(
value = "detail2",
title = "Sepal Width",
reactable(
data = filter(nested2, Species == specie),
fullWidth = FALSE
)
),
tabPanel(
value = "detail3",
title = "Pedal Length",
reactable(
data = filter(nested3, Species == specie),
fullWidth = FALSE
)
),
tabPanel(
value = "detail4",
title = "Pedal Width",
reactable(
data = filter(nested4, Species == specie),
fullWidth = FALSE
)
)
)
})
})
}
shinyApp(ui = ui, server = server)
#>
<sup>Created on 2021-11-15 by the [reprex package](https://reprex.tidyverse.org) (v2.0.1)</sup>
Your radioButtons
is confusing as the selection corresponds to each tab. Therefore, it is best to updateRadioButtons
each time you select a different tab. If you do so, it will re-render the output$table
, as you are using input$selected_detail
. With that said, the following works...kind of. It closes the tabs as soon as you select a tab, as Input$tabs
is set to NULL
due to rerendering of the reactable. You can open it the second time and the tables are not overlapping. Perhaps there is a better way to do it using javascript. Try this
main_table <- iris %>%
select(Species) %>%
unique()
nested1 <- iris %>%
select(Species, Sepal.Length)
nested2 <- iris %>%
select(Species, Sepal.Width)
nested3 <- iris %>%
select(Species, Petal.Length)
nested4 <- iris %>%
select(Species, Petal.Width)
ui <- dashboardPage(
dashboardHeader(title = "Nested Reactables"),
dashboardSidebar(
radioButtons(inputId = "selected_detail",
label = "Select default tabPanel",
choices = c("detail1",
"detail2",
"detail3",
"detail4",
"empty string")
)
),
dashboardBody(
reactableOutput("table")
)
)
server <- function(input, output, session) {
output$table <- renderReactable({
myselection <- input$selected_detail
reactable(
data = main_table,
details = function(index) {
specie <- main_table$Species[[index]]
tabsetPanel(id = "tabs",
selected = paste0(myselection,index),
type = c("tabs"),
tabPanel(
value = paste0("detail1",index),
title = "Sepal Length",
reactable(
data = dplyr::filter(nested1, Species == specie) %>% select(-Species),
fullWidth = FALSE
)
),
tabPanel(
value = paste0("detail2",index),
title = "Sepal Width",
reactable(
data = dplyr::filter(nested2, Species == specie),
fullWidth = FALSE
)
),
tabPanel(
value = paste0("detail3",index),
title = "Petal Length",
reactable(
data = dplyr::filter(nested3, Species == specie),
fullWidth = FALSE
)
),
tabPanel(
value = paste0("detail4",index),
title = "Petal Width",
reactable(
data = dplyr::filter(nested4, Species == specie),
fullWidth = FALSE
)
)
)
})
})
observeEvent(input$tabs, {
if (!is.null(input$tabs)) {
value <- input$tabs
valu <- substr(value,1,7)
updateRadioButtons(session, 'selected_detail', selected = valu)
}
})
observe({
print(input$tabs)
})
}
shinyApp(ui = ui, server = server)