I'm creating a R Shiny App that contains three tabs. I would like to display a filter on the first two tabs and no filter on the third tab. I would like the filter on tabs one and two to be synchronized.
library(shiny)
server <- function(input, output, session) {
dataset <- reactive({
get(input$dataset, "package:datasets")
})
output$summary <- renderPrint({
summary(dataset())
})
output$table <- renderTable({
dataset()
})
output$table_head <- renderTable({
head(dataset())
})
}
ui <- fluidPage(
tabsetPanel(type = "tabs",
tabPanel(title = "tab one filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
verbatimTextOutput("summary")
)
)
),
tabPanel(title = "tab two filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
tableOutput("table")
)
)
),
tabPanel(title = "tab three unfiltered",
mainPanel(
tableOutput("table_head")
)
)
)
)
shinyApp(ui, server)
My code is very similar to this. When I run this, the filter on the second page does not work. How can I display a synchronized filter on the first two tabs and no filter on the third tab. I've seen the suggestion to have the selectInput
outside of the tabsetPanel
but the filter will show on the third page. Thanks for the help.
CodePudding user response:
You can't have two elements with the same ID in a given layout. So first you'll want to given them separate IDs
tabPanel(title = "tab one filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset1", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
verbatimTextOutput("summary")
)
)
),
tabPanel(title = "tab two filtered",
sidebarLayout(
sidebarPanel(
selectInput("dataset2", label = "filter", choices = ls("package:datasets"))
),
mainPanel(
tableOutput("table")
)
)
),
then you'll need to do some extra work in the server to keep them insync.
server <- function(input, output, session) {
datasetname <- reactiveVal(ls("package:datasets")[1])
observeEvent(input$dataset1, {
updateSelectInput(session, "dataset2", selected=input$dataset1)
datasetname(input$dataset1)
})
observeEvent(input$dataset2, {
updateSelectInput(session, "dataset1", selected=input$dataset2)
datasetname(input$dataset2)
})
dataset <- reactive({
get(datasetname(), "package:datasets")
})
...
}
We keep a separate reactive value datasetname
to keep track of the active name. Then we update the UI when one of the two dataset1/dataset2 values changes.