I am currently trying to make a Flexdashboard shiny app. I want to be able to display different UI in my sidebar given which tab is active in my output zone.
For this I considered using a renderUI
and some basic conditions. But my problem is that I don't know how to get the active tab in flexdashboard. I have done some research but I wasn't able to find the info. I am not sure if we can add id to a tabset as in shiny and if it is possible, how to get the result corresponding to the id.
Here is some skeleton code of what I would like to do :
---
title: "Test"
runtime: shiny
output:
flexdashboard::flex_dashboard:
vertical_layout: scroll
---
```{r setup, include=FALSE}
suppressPackageStartupMessages({
library(shiny)
library(flexdashboard)
})
```
# Page 1
## Input {.sidebar}
```{r}
radioButtons("radio", label = h3("Radio buttons"),
choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3),
selected = 1)
output$list1 <- renderUI({
if (tab == "Tabs 1") {
selectInput("select", label = h3("Select box"),
choices = list("Choice 1" = 1, "Choice 2" = 2, "Choice 3" = 3),
selected = 1)
}
else {}
})
uiOutput("list1")
```
Column {.tabset }
-------------------------------------
### Tab 1
### Tab 2
### Tab 3
Thanks for your help :)
It seems that unlike in the tabsetPanel(..., id = "xyz")
case where there is a input$xyz
variable created, Rmarkdown
does not show the same courtesy.
Hence, we need to hack that functionality ourselves with the help of a bit JavaScript:
---
title: "Test"
runtime: shiny
output:
flexdashboard::flex_dashboard:
vertical_layout: scroll
---
<script>
$("body").on("shown.bs.tab", "a[data-toggle='tab']", function(e) {
Shiny.setInputValue("active_tab", $(e.target).parent().index());
})
</script>
We are telling shiny
that whenever a tab is shown, we want to set an input variable (i.e. something we can react upon on the shiny
side) to the corresponding tab number (0 based).
We can then use input$active_tab
to set our server logic:
output$list1 <- renderUI({
sel <- input$active_tab
if (is.null(sel) || sel == 0) {
selectInput("select", label = h3("Select box"),
choices = list("Choice A1", "Choice A2", "Choice A3"),
selected = 1)
} else if (sel == 1) {
selectInput("select", label = h3("Select box"),
choices = list("Choice B1", "Choice B2", "Choice B3"),
selected = 1)
} else {
selectInput("select", label = h3("Select box"),
choices = list("Choice C1", "Choice C2", "Choice C3"),
selected = 1)
}
})
Note. I guess that there is a better event rather than shown.bs.tab
to which you can attach the event handler. This may help to avoid testing for the NULL
case in teh render
part. This happens, because apparently shown.bs.tab
does not fire when the first tab is shown by default.