Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny synchronize filters on multiple tabs

Tags:

r

shiny

I built a R Shiny application with multiple tabs, which have some filters in common. Right now, all filters are stand-alone and do not synchronize across multiple tabs. Hence, when I change selectInput1 from value "a" to value "b", I have to repeat this handling on the next tab which contains selectInput2 with the same options/meaning.

I thought about making the filters dynamic, hence rendering them using the server side of R Shiny. Then of course, I can always make selectInput2 equal to selectInput1. But what if the user changes selectInput2 rather than selectInput1? It creates kind of a loop in the logic.

I spent quite some time finding a solution for this problem, and somehow I'm sure I'm not the first one encountering this problem. Suggestions or useful links would be really helpful!

Example:

## UI.R
shinyUI(
  dashboardPage("Dashboard",

    # Create tabs
    tabPanel("Start",
             p("This is the frontpage")
    ),
    tabPanel("tab1",
             uiOutput("selectInput1")
    ),
    tabPanel("tab2",
             uiOutput("selectInput2")
    )
  )
)

and:

## Server.R
library(shiny)

shinyServer(function(input, output,session){
  output$selectInput1 <- renderUI({
    selectInput(inputId = "id1", 
                label = "select", 
                choices = c("a","b","c"), 
                selected = "a")
  })

  output$selectInput2 <- renderUI({
    selectInput(inputId = "id2", 
                label = "select", 
                choices = c("a","b","c"), 
                selected = "a")
  })
})
like image 342
Dendrobates Avatar asked Jun 13 '17 08:06

Dendrobates


1 Answers

I would personally use a single input control to control the different tab panels. One way is to include that single input under your tabs:

shinyApp(
  fluidPage(
    fluidRow(
      tabsetPanel(
        tabPanel("Tab1",
                 verbatimTextOutput("choice1")),
        tabPanel("Tab2",
                 verbatimTextOutput("choice2"))
      )
    ),
    fluidRow(
      selectInput("id1", "Pick something",
                  choices = c("a","b","c"),
                  selected = "a")
    )
  ),
  function(input, output, session){
    output$choice1 <- renderPrint(input$id1)
    output$choice2 <- renderPrint({
      paste("The choice is:", input$id1)
    })
  }
)

Or, as you use a shinydashboard, you could actually add that control in the sidebar, possibly again in its own row under a set of tabs if you must.

I can't think of a reason to have multiple inputs who automatigically select the same thing. Other than slowing down your app, I can't see any gain. But if you insist, you make the selected choice a reactive value using reactiveVal and you use eg observeEvent() to update that reactive value. A small example using shinydashboard:

library(shinydashboard)
library(shiny)
ui <- shinyUI(
  dashboardPage(title = "Dashboard",
                dashboardHeader(),
                dashboardSidebar(
                  tabsetPanel(
                  tabPanel("tab1",
                           uiOutput("selectInput1")
                  ),
                  tabPanel("tab2",
                           uiOutput("selectInput2")
                  )
                )),
                dashboardBody(
                  verbatimTextOutput("selected")
                )
  )
)

server <- shinyServer(function(input, output,session){

  thechoice <- reactiveVal("a")  
  output$selectInput1 <- renderUI({
    selectInput(inputId = "id1", 
                label = "select", 
                choices = c("a","b","c"), 
                selected = thechoice())
  })
  output$selectInput2 <- renderUI({
    selectInput(inputId = "id2", 
                label = "select", 
                choices = c("a","b","c"), 
                selected = thechoice())
  })

  observeEvent(input$id2,{
    thechoice(input$id2)
  })

  observeEvent(input$id1,{
    thechoice(input$id1)
  })

  output$selected <- renderPrint({
    c(input$id1, input$id2)
  })
})

shinyApp(ui, server)
like image 148
Joris Meys Avatar answered Oct 02 '22 00:10

Joris Meys