Search code examples
rshinyshinydashboard

How do I sort values in a shiny app dropdown menu


This is the code I am currently working with:

library(shiny)
library(data.table)

# Create the data table
dt <- data.table(
  name = c("")
)

# Define the Shiny app UI
ui <- fluidPage(
  tags$head(
    tags$style(HTML("
      .wrapper {
        max-width: 1300px;
        margin-left: auto;
        margin-right: auto;
      }
      @media (min-width: 1300px) {
        .wrapper {
          margin-left: auto;
          margin-right: auto;
        }
      }
    "))
  ),
  # Wrap the contents of the page in a div with the wrapper class
  div(class = "wrapper",
      # Add a file input button
      fileInput("file", "Upload CSV file"),
      # Add a sidebar layout
      sidebarLayout(
        # Add a sidebar panel
        sidebarPanel(
          # Add checkboxes for each column in the data table
          checkboxGroupInput("columns", "Columns:", names(dt), selected = NULL),
          # Add a dropdown menu for the unique values of each selected column
          uiOutput("values")
        ),
        # Add a main panel
        mainPanel(
          # Add a data table to the main panel
          DT::dataTableOutput("table")
        )
      )
  )
)


# Define the Shiny app server logic
server <- function(input, output, session) {
  # Read the CSV file and replace the existing data in dt
  observeEvent(input$file, {
    if (is.null(input$file)) return()
    dt <<- fread(input$file$datapath)
    # Update the checkboxGroupInput with the names of the new data in dt
    updateCheckboxGroupInput(session, "columns", choices = names(dt), selected = names(dt)[1])
  })
  
  # Create a reactive expression for the unique values of the selected columns
  values <- reactive({
    lapply(input$columns, function(x) {
      selectInput(x, x, c("All", unique(dt[, x, with = FALSE])), selected = "All")
    })
  })
  
  # Render the dropdown menus
  output$values <- renderUI({
    tagList(values())
  })
  
  # Create a reactive expression for the subset of the data table
  subset <- reactive({
    filters <- lapply(input$columns, function(x) {
      if (input[[x]] == "All") {
        TRUE
      } else {
        dt[[x]] %in% input[[x]]
      }
    })
    dt[Reduce(`&`, filters), ]
  })
  
  # Render the data table
  output$table <- DT::renderDataTable({
    subset()
  }, options = list(pageLength = 100))  # set pageLength = 100 to show 100 entries by default
  
}

# Run the Shiny app
shinyApp(ui, server)

The idea is that when new data is uploaded via a browse button prompt, radio buttons appear to select columns, and for the columns selected, dropdown menus are dynamically created that subset displayed data according to the unique values.

I want to modify the code so that the unique values in the dropdown menus are sorted, yet I can't for the life of me figure out how to modify the code without creating errors in reading the data.


Solution

  • I changed this line of code:

    selectInput(x, x, c("All", unique(dt[, x, with = FALSE])), selected = "All")
    

    to this:

    selectInput(x, x, c("All", unique(dt[order(dt[, x, with = FALSE]), x, with = FALSE])), selected = "All")
    

    The sort() function kept producing errors, but order() worked.