2

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 :)

makeyourownmaker
  • 1,558
  • 2
  • 13
  • 33
Glastos
  • 47
  • 10

1 Answers1

2

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.

thothal
  • 16,690
  • 3
  • 36
  • 71
  • Thanks a lot, it is working ! Do you know if it would be possible to adapt it to give different id to different `tabset` ? – Glastos Oct 13 '20 at 08:42
  • I am not so deeply involved in `rmarkdown` so no idea. But with JS you can add `ids` if you like, why would you need different ids for the `tabsets`? – thothal Oct 13 '20 at 08:46
  • Ah ok, I am not a JS developer but I might consider learning it in the future for cases like this. It was because in my main app, I have different pages (first row of tabs) and in the second page, I have three tabs (second row of tabs) and because of that, if I use your solution when I click on my second page, it consider that it should display the UI for the second tab even if it is in the first one. This is why I was considering adding id for each `tabsets`. But I worked around a different layout to use your solution so it is ok :) – Glastos Oct 13 '20 at 11:43
  • 1
    Replace the `JS` function body by `Shiny.setInputValue("active_tab", $(this).attr('id'));` in this way, the `active_tab` will contain the `id` of the tab rather than the order. – thothal Oct 13 '20 at 11:52