Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change second tabset on click in flexdashboard

I'm working on a self-contained flexdashboard project and I'm wondering if it's possible when a user clicks to a new tab in one tabset, it changes to a new tab on a second tabset as well.

So for example, when you click on "Chart B1" below, I would also like to change view to "Chart B2" in the second column. And clicking on "Chart A2" would change back to "Chart A1", etc. etc.

enter image description here

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(flexdashboard)
```

Column {.tabset}
-----------------------------------------------------------------------

### Chart A1

### Chart B1

Column {.tabset}
-----------------------------------------------------------------------

### Chart A2

### Chart B2

Note, this was first posted on RStudio Community, but did not receive any responses.

like image 247
mfherman Avatar asked Apr 27 '20 12:04

mfherman


People also ask

Is it possible to add tabs to flexdashboard?

Just found out that it is not currently possible as tabs have to cover full row github.com/rstudio/flexdashboard/issues/37. # Your tabset title ================================ (tabset content) I'm running version 1.0.143 of R-Studio, version 1.8 of rmarkdown, and 0.5.1 version of flexdashboard. Tabs work nicely with flexdashboard.

What are the different title levels in a flexdashboard?

With flexdashboard, title levels have different meaning, and the first 3 each serves a purpose. Level 2 are for definining the layout, Row or Column. See about orientation Level 3 are for defining the component, and define the title of each boxes. See about title. They are also uses to defines tabset name (See about tab row

How do I set the width of charts in flexdashboard?

The width of charts in flexdashboard is ultimately determined by the width of the browser. If your layout has a single column then charts will occupy the full width of the browser. If your layout has multiple columns then the columns will split the available width evenly (unless overridden via the data-width attribute as described below).

How do I set up a flexdashboard using Cran?

To set up a flexdashboard, install the package from CRAN using the standard command. To get started, enter the following into the console: This function creates a .Rmd file with the name associated file name, and uses the package’s flexdashboard template.


2 Answers

This can be implemented with JavaScript. Luckily, Knitr supports embedded Javascript. I am an R programmer foremost, so this may not necessarily be the most concise implementation, but it does achieve the correct effect.

    ---
    title: "Untitled"
    output: 
      flexdashboard::flex_dashboard:
        orientation: columns
        vertical_layout: fill
    ---

    ```{r setup, include=FALSE}
    library(flexdashboard)
    ```

    Column {.tabset}
    -----------------------------------------------------------------------

    ### Chart A1
    Chart A1 is Great

    ### Chart B1
    Chart B1 is Great

    Column {.tabset}
    -----------------------------------------------------------------------

    ### Chart A2
    Chart A2 is Great

    ### Chart B2
    Chart B2 is Great

    ```{js}
    // Once the Document Has Fully Loaded
    document.addEventListener("DOMContentLoaded", function(){
      // Select The Tabs
      window.a1Tab = document.querySelector("#column > ul > li:nth-child(1)");
      window.b1Tab = document.querySelector("#column > ul > li:nth-child(2)");
      window.a2Tab = document.querySelector("#column-1 > ul > li:nth-child(1)");
      window.b2Tab = document.querySelector("#column-1 > ul > li:nth-child(2)");

      // Select the Panel Content
      window.a1Panel = document.getElementById('chart-a1');
      window.b1Panel = document.getElementById('chart-b1');
      window.a2Panel = document.getElementById('chart-a2');
      window.b2Panel = document.getElementById('chart-b2');

      // If We Click on B1, Open B2, Close A2
      b1Tab.addEventListener('click', function(){
        a2Tab.classList.remove('active');
        a2Tab.children[0].setAttribute('aria-expanded', true);
        a2Panel.classList.remove('active');

        b2Tab.classList.add('active');
        b2Tab.children[0].setAttribute('aria-expanded', true);
        b2Panel.classList.add('active');
      }, false);

      // If We Click on B2, Open B1, Close A1
      b2Tab.addEventListener('click', function(){
        a1Tab.classList.remove('active');
        a1Tab.children[0].setAttribute('aria-expanded', true);
        a1Panel.classList.remove('active');

        b1Tab.classList.add('active');
        b1Tab.children[0].setAttribute('aria-expanded', true);
        b1Panel.classList.add('active');
      }, false);

      // If We Click on A1, Open A2, Close B2
      a1Tab.addEventListener('click', function(){
        b2Tab.classList.remove('active');
        b2Tab.children[0].setAttribute('aria-expanded', true);
        b2Panel.classList.remove('active');

        a2Tab.classList.add('active');
        a2Tab.children[0].setAttribute('aria-expanded', true);
        a2Panel.classList.add('active');
      }, false);

      // If We Click on A2, Open A1, Close B1
      a2Tab.addEventListener('click', function(){
        b1Tab.classList.remove('active');
        b1Tab.children[0].setAttribute('aria-expanded', true);
        b1Panel.classList.remove('active');

        a1Tab.classList.add('active');
        a1Tab.children[0].setAttribute('aria-expanded', true);
        a1Panel.classList.add('active');
      }, false);
    });

    ```

Edit: For an unlimited number of tabs, assuming that you will always have the same number of tabs in the first and second column. Same disclaimer, this is not necessarily the most concise implementation, but achieves the desired effect.


    ---
    title: "Untitled"
    output: 
      flexdashboard::flex_dashboard:
        orientation: columns
        vertical_layout: fill
    ---

    ```{r setup, include=FALSE}
    library(flexdashboard)
    ```

    Column {.tabset}
    -----------------------------------------------------------------------

    ### Chart A1
    Chart A1 is Great

    ### Chart B1
    Chart B1 is Great

    ### Chart C1
    Chart C1 is Great

    ### Chart D1
    Chart D1 is Great

    Column {.tabset}
    -----------------------------------------------------------------------

    ### Chart A2
    Chart A2 is Great

    ### Chart B2
    Chart B2 is Great

    ### Chart C2
    Chart C2 is Great

    ### Chart D2
    Chart D2 is Great

    ```{js}
    // Once the Document Has Fully Loaded
    document.addEventListener("DOMContentLoaded", function(){
      // Select The Tabs
      window.col1Tabs = document.querySelector("#column > ul");
      window.col2Tabs = document.querySelector("#column-1 > ul");

      // Select the Panel Content
      window.col1Panels = document.querySelector("#column > div");
      window.col2Panels = document.querySelector("#column-1 > div");

      // Function to Make Tabs Active
      window.handleTab = function(tabIndex){
        for(i=0;i<col1Tabs.childElementCount;i++){
          col1Tabs.children[i].classList.remove('active');
          col2Tabs.children[i].classList.remove('active');
          col1Panels.children[i].classList.remove('active');
          col2Panels.children[i].classList.remove('active');
        }
        col1Tabs.children[tabIndex].classList.add('active');
        col2Tabs.children[tabIndex].classList.add('active');
        col1Panels.children[tabIndex].classList.add('active');
        col2Panels.children[tabIndex].classList.add('active');
      }

      // For All Tabs, Add Event Listener
      for(i=0;i<col1Tabs.childElementCount;i++){
        col1Tabs.children[i].setAttribute('onclick', 'handleTab(' + i + ');');
        col2Tabs.children[i].setAttribute('onclick', 'handleTab(' + i + ');');
      }

    });

    ```

Edit: For anyone who may find this question later, a JQuery implementation with more flexibility was added to the Github Issue.

like image 178
Branson Fox Avatar answered Oct 28 '22 01:10

Branson Fox


Just to add another answer using JQuery and boostrap tabset JS function. It is more concise than other answer but works the same with any number of tabs (but the same number) in your two column format.

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(flexdashboard)
```

```{js}
document.addEventListener("DOMContentLoaded", function(){
    $('a[data-toggle="tab"]').on('click', function(e){
      // find the tab index that is click
      child = e.target.parentNode;
      tabnum = Array.from(child.parentNode.children).indexOf(child);
      // find in which column we are
      column = $(e.target).closest("div[id]");
      // show the same tab in the other column
      columnid = column.attr("id");
      if (columnid == "column") {
        columnto = "column-1";
      } else {
        columnto = "column";
      }
      $("div[id="+columnto+"] li:eq("+tabnum+") a").tab('show');
    })
});
```

Column {.tabset}
-----------------------------------------------------------------------

### Chart A1

This is a text

### Chart B1

```{r}
plot(iris)
```


Column {.tabset}
-----------------------------------------------------------------------

### Chart A2

```{r}
plot(mtcars)
```

### Chart B2

This is another text

like image 30
cderv Avatar answered Oct 28 '22 02:10

cderv