Search code examples
rshinyflexdashboard

Find out what page is the user looking at


How can I determine if the user is looking at a particular page in a flexdashboard? I have a global sidebar panel of filters that applies to all pages except one of the filters in the sidebar doesn't apply to one of the pages. In this example, let's say I don't want the selectInput() to be displayed on Page 3.

---
title: "Which Page?"
runtime: shiny
output: flexdashboard::flex_dashboard
---

Sidebar {.sidebar data-width=400}
=====================================
```{r}
textInput("text", NULL)

selectInput("select", NULL, LETTERS[1:5])
```

Page 1
=====================================

Page 2
=====================================

Page 3
=====================================

I was hoping to use session$clientData$url_hash but this is static and based on the page the user initially opened. You can put this in the sidebar section to see how it (doesn't) change. Other ideas I've found are to use window.location or is.visible in js but not sure how to integrate.

print_info <- function(x) {
  allvalues <- 
    lapply(
      X = sort(names(x)), 
      FUN = function(name) {
        item <- x[[name]]
        paste(name, item, sep = " = ")
      }
    )
  
  paste(allvalues, collapse = "\n")
}
    
output$client_data <- renderText(print_info(session$clientData))
verbatimTextOutput("client_data")

Solution

  • Solution 1 : "pure Shiny"

    You can take advantage of the fact that renderXXX() is only calculated on active page. For example here we can use renderUI() on each page to update a reactive value tab with the current page number. That value is then used in the side bar to check if the selectInput will be displayed with the renderUI :

    ---
    title: "Which Page?"
    runtime: shiny
    output: flexdashboard::flex_dashboard
    ---
    
    Sidebar {.sidebar data-width=400}
    =====================================
    ```{r}
    textInput("text", NULL)
    
    tab <- reactiveVal(1)
    renderUI({
      if(tab()!=3)
        selectInput("select", NULL, LETTERS[1:5])
    })
    ```
    
    Page 1
    =====================================
    ```{r}
    renderUI({tab();tab(1);NULL})
    ```
    
    Page 2
    =====================================
    ```{r}
    renderUI({tab();tab(2);NULL})
    ```
    
    Page 3
    =====================================
    ```{r}
    renderUI({tab();tab(3);NULL})
    ```
    

    Solution 2 : with JavaScript

    You can also use a JS event

    (note the use of is.null() as event is not triggered on page 1 initial display):

    ---
    title: "Which Page?"
    runtime: shiny
    output: flexdashboard::flex_dashboard
    ---
    
    <script>
    $("body").on("shown.bs.tab", "a[data-toggle='tab']", function(e) {
       Shiny.setInputValue("active_tab", $(e.target).parent().index() + 1);
    })
    </script>
    
    Sidebar {.sidebar data-width=400}
    =====================================
    ```{r}
    textInput("text", NULL)
    
    renderUI({
      if(is.null(input$active_tab) || input$active_tab!=3)
        selectInput("select", NULL, LETTERS[1:5])
    })
    ```
    
    Page 1
    =====================================
    
    Page 2
    =====================================
    
    Page 3
    =====================================