Reputation: 239
Unable to make the similar functionality of filters which should be interdependent. So that means if user select a input from one filter, all other filters should get updated.
I have tried multiple ways in shiny but unable to do so however found some code on stackoverflow with similar functionality. The only challenge is that i don't want to show the table as a output and unfortunately the code does not work if we don't pass the output to #tableprint [id of a table].
Any help would be really appreciated.
library(shiny)
library(dplyr)
library(DT)
ui <- fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(width=3,
selectInput("filter1", "Filter 1", multiple = TRUE, choices = c("All", LETTERS)),
selectInput("filter2", "Filter 2", multiple = TRUE, choices = c("All", as.character(seq.int(1, length(letters), 1)))),
selectInput("filter3", "Filter 3", multiple = TRUE, choices = c("All", letters)) ),
mainPanel(
DT::dataTableOutput("tableprint")
)
)
)
server <- function(input, output, session) {
output$tableprint <- DT::renderDataTable({
# Data
df <- tibble(LETTERS = rep(LETTERS, 2), Numbers = as.character(1:52),
letters = paste(LETTERS, Numbers, sep = ""))
df1 <- df
if("All" %in% input$filter1){
df1
} else if (length(input$filter1)){
df1 <- df1[which(df1$LETTERS %in% input$filter1),]
}
# Update selectInput choices based on the filtered data. Update 'selected' to reflect the user input.
updateSelectInput(session, "filter1", choices = c("All", df$LETTERS), selected = input$filter1)
updateSelectInput(session, "filter2", choices = c("All", df1$Numbers), selected = input$filter2)
if("All" %in% input$filter2){
df1
} else if (length(input$filter2)){
df1 <- df1[which(df1$Numbers %in% input$filter2),]
}
updateSelectInput(session, "filter3", choices = c("All", df1$letters), selected = input$filter3)
if("All" %in% input$filter3){
df1
} else if (length(input$filter3)){
df1 <- df1[which(df1$letters %in% input$filter3),]
}
datatable(df1)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 1
Views: 1184
Reputation: 29407
You can do something like this: its a lot cleaner and easier to read. Note that I added the shinyWidgets
package which has the pre-built Select-All
Button. You can use the variable called v$df
in your other reactives as you said I dont want to show the table as output
library(shiny)
library(dplyr)
library(DT)
library(shinyWidgets)
# Install shinyWidgets
# From CRAN
#install.packages("shinyWidgets")
# From Github
# install.packages("devtools")
#devtools::install_github("dreamRs/shinyWidgets")
df <- tibble(LETTERS = rep(LETTERS, 2), Numbers = as.character(1:52),letters = paste(LETTERS, Numbers, sep = ""))
ui <- fluidPage(
titlePanel("Title"),
sidebarLayout(
sidebarPanel(width=3,
pickerInput("filter1", "Filter 1", choices = LETTERS, options = list(`actions-box` = T), multiple = T),
pickerInput("filter2", "Filter 2", choices = df$Numbers, options = list(`actions-box` = T), multiple = T),
pickerInput("filter3", "Filter 3", choices = letters, options = list(`actions-box` = T), multiple = T)),
mainPanel(
DT::dataTableOutput("tableprint")
)
)
)
server <- function(input, output, session) {
v <- reactiveValues()
observe({
dt <- df$Numbers[df$LETTERS %in% input$filter1]
updatePickerInput(session, "filter2", choices = dt,selected = dt)
})
observe({
dt <- df$letters[df$Numbers %in% input$filter2]
updatePickerInput(session, "filter3", choices = dt,selected = dt)
})
output$tableprint <- DT::renderDataTable({
df <- df[df$LETTERS %in% input$filter1,]
df <- df[df$Numbers %in% input$filter2,]
df <- df[df$letters %in% input$filter3,]
v$df <- df
datatable(df)
})
}
# Run the application
shinyApp(ui = ui, server = server)
Upvotes: 2