Как заставить текущую активную вкладку в документе Flexdashboard реактивно отображать другой пользовательский интерфейс

#r #shiny #r-markdown #flexdashboard

#r #блестящий #r-markdown #flexdashboard

Вопрос:

В настоящее время я пытаюсь сделать приложение Flexdashboard блестящим. Я хочу иметь возможность отображать другой пользовательский интерфейс на своей боковой панели, учитывая, какая вкладка активна в моей зоне вывода.

Для этого я рассмотрел возможность использования a renderUI и некоторых основных условий. Но моя проблема в том, что я не знаю, как получить активную вкладку в flexdashboard. Я провел некоторое исследование, но не смог найти информацию. Я не уверен, можем ли мы добавить идентификатор в набор вкладок, как в shiny, и если это возможно, как получить результат, соответствующий идентификатору.

Вот некоторый скелетный код того, что я хотел бы сделать :

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

Спасибо за вашу помощь 🙂

Ответ №1:

Кажется, что в отличие от tabsetPanel(..., id = "xyz") случая, когда создается input$xyz переменная, Rmarkdown не проявляет такой же вежливости.

Следовательно, нам нужно взломать эту функциональность самостоятельно с помощью немного 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>
  

Мы говорим shiny , что всякий раз, когда отображается вкладка, мы хотим установить входную переменную (т. Е. То, На что мы можем реагировать shiny сбоку) на соответствующий номер вкладки (на основе 0).

Затем мы можем использовать input$active_tab для настройки нашей серверной логики:

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

Примечание.Я предполагаю, что есть лучшее событие, а не shown.bs.tab то, к которому вы можете прикрепить обработчик событий. Это может помочь избежать тестирования для NULL случая в render этой части. Это происходит потому, что, по-видимому shown.bs.tab , не срабатывает, когда по умолчанию отображается первая вкладка.

Комментарии:

1. Большое спасибо, это работает! Вы знаете, можно ли было бы адаптировать его, чтобы присвоить другой идентификатор другому tabset ?

2. Я не так глубоко вовлечен, rmarkdown поэтому понятия не имею. Но с помощью JS вы можете добавить ids , если хотите, зачем вам нужны разные идентификаторы для tabsets ?

3. Ах, хорошо, я не разработчик JS, но я мог бы рассмотреть возможность изучения этого в будущем для подобных случаев. Это было потому, что в моем основном приложении у меня есть разные страницы (первый ряд вкладок), а на второй странице у меня есть три вкладки (второй ряд вкладок), и из-за этого, если я использую ваше решение при нажатии на мою вторую страницу, оно считает, что оно должно отображать пользовательский интерфейс для второй вкладки, даже если она находится в первой. Вот почему я рассматривал возможность добавления идентификатора для каждого tabsets из них . Но я работал с другим макетом, чтобы использовать ваше решение, так что все в порядке 🙂

4. Замените JS тело функции Shiny.setInputValue("active_tab", $(this).attr('id')); на таким образом, active_tab чтобы оно содержало id табуляцию, а не порядок.