I have an interesting problem with the selectizeInput()
function. I am not sure if this is a bug or if it's a problem with how I am handling the dataset.
In the context of my reproducible code example provided below, I have this to test:
sum(cars$cyl==4 | cars$cyl==6)
The total records displayed should = 18.
However, using the reproducible code provided below, if you were to use the selectizeInput()
for the ID value of cars$cyl
, the number of records displayed is not correct.
If you select "4" and the "6" (in that order), it returns 10 records. But if you select "6" and then "4" it returns 8 records. In neither case does it return the correct value of 18. (Yet 10+8 does indeed = 18).
What is going on? Why is it that when I select multiple values it does not retrieve the correct number of records associated with the cars$cyl
category?
Reproducible Code:
## ----- LOAD REQUIRED PACKAGES -----
library(shiny)
library(DT)
library(ggplot2)
library(shinyjs)
## ------ LOAD EXAMPLE DATA ------
cars = mtcars
## ==== UI ====
ui <- fluidPage(
useShinyjs(),
titlePanel("A DataTable"),
fluidRow(
column(4,
textInput("reportText", label="Report Name", value="Enter Report Name", width=NULL))
),
# Create a new Row in the UI for selectInputs
fluidRow(
column(4,
selectizeInput("cyl",
"Cylinders:",
c("All",
unique(as.character(cars$cyl))), multiple = TRUE)
),
column(4,
selectizeInput("gear",
"Gears:",
c("All",
unique(as.character(cars$gear))), multiple = TRUE)
),
column(4,
selectizeInput("carb",
"Carburators:",
c("All",
unique(as.character(cars$carb))), multiple = TRUE)
)
),
# Create a new row for the table.
DT::dataTableOutput("dt"),
# Create a new row for the download button
downloadButton(outputId = "download_filtered",
label = "Download Filtered Data"),
# Create a new row for the reset button
actionButton("clear", label = "Clear all filters", icon ("eraser"), class = "down")
)
## ==== END UI ====
## ==== SERVER ====
server = function(input, output, session){
# ---Reset Filters Button -----
observeEvent(input$clear, {
updateTextInput(session, "reportText", label = "Enter Report Name", value = "Enter Report Name")
updateSelectizeInput(session,"cyl", label = "Filter Cylinder:",
choices = c("All",
unique(sort(as.character(cars$cyl)))))
updateSelectizeInput(session,"gear",label = "Filter Gear",
choices = c("All",
unique(as.character(cars$gear))))
updateSelectizeInput(session,"carb", label = "Filter Carb",
choices = c("All",
unique(as.character(cars$carb))))
})
## Create a reactive DF function for filters:
reactiveDF = reactive({
cardata <- cars
# conditionals
if (input$cyl != "All") {
cardata <- cardata[cardata$cyl == input$cyl, ]
}
if (input$gear != "All") {
cardata <- cardata[cardata$gear == input$gear, ]
}
if (input$carb != "All") {
cardata <- cardata[cardata$carb == input$carb, ]
}
# display the filtered data
cardata
})
output$filtered_row <-
renderPrint({
input[["dt_rows_all"]]
})
## Output Datatable -------
output$dt <- DT::renderDataTable(datatable({
reactiveDF()
}))
output$download_filtered <-
downloadHandler(
filename = function() {
repname <- "filtered_report.csv"
if (isTruthy(input$reportText)) {
if (input$reportText != "Enter Report Name") {
repname <- paste(input$reportText, ".csv", sep="")
}
}
repname
},
content = function(file) {
write.csv(reactiveDF(), file)
}
)
# Reset button observe event
observeEvent(input$clear, {
shinyjs::reset("filter-pane")
})
}
shinyApp(ui,server)