Home > Enterprise >  How to display all filters in a continuous line in a shiny app?
How to display all filters in a continuous line in a shiny app?

Time:11-05

Goal

I watched this enter image description here

Code

The code is not shared in the description unfortunately. So, I wrote it down while watching the video. But it did not display the filters as the video shows. I think there is some CSS trickery here. Anyways, the code is here:

library(shiny)
library(dplyr)
# library(imola)

filter_preposition <- function(prefix_text, input, suffix_text){
  div(
    class = "filter-preposition",
    prefix_text, input, suffix_text
  )
}



filter_query <- function(prefix_text = "", ..., suffix_text = ""){
  div(
    class = "filter-query",
    prefix_text, ..., suffix_text
  )
}


filters <- filter_query(
  prefix_text = "Show me",

  filter_preposition(
    "",
    selectInput("quantity", "", c(5, 10, 15)),
    "cars,"
  ),

  filter_preposition(
    "that have",
    selectInput("gear", "", sort(unique(mtcars$gear))),
    "gears"
  ),

  filter_preposition(
    "with at least",
    numericInput("hp", "", min(mtcars$hp),
                 step = 5,
                 min = min(mtcars$hp),
                 max = max(mtcars$hp)
                 ),
    "horse power,"
  ),

  filter_preposition(
    "and that consumes at most",
    numericInput(
      "mpg", "", 50,
      step = 10,
      min = min(mtcars$mpg),
      max = 50
    ),
    "miles per gallon."
  ),

  suffix_text = ""

)

# ui <- gridPage(
#   areas = list("filters", "output"),
#   rows = c("auto", "1fr"),
#   filters = flexPanel(filters),
#   output = tableOutput("results")
# )


ui <- fluidPage(

  tags$head(
    tags$style(
      HTML(
        "
        .filter-query {
          display: flex;
          align-items: center;
        }

        .filter_preposition {
          margin-right: 10px; /* Adjust as needed */
        }
        "
      )
    )
  ),


  filters, tableOutput("results")
)


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

  observeEvent(c(input$quantity, input$hp, input$gear, input$mpg),{

    results <- mtcars

    if (!is.null(input$gear)){
      results <- results |>
        filter(gear == as.numeric(input$gear))
    }


    if (!is.null(input$hp)){
      results <- results |>
        filter(hp >= input$hp)
    }

    if (!is.null(input$mpg)){
      results <- results |>
        filter(mpg <= input$mpg)
    }


    if (!is.null(input$quantity)){
      results <- results |>
        slice_head(n = as.numeric(input$quantity))
    }


    output$results <- renderTable(results, rownames = TRUE)

  })
}


shinyApp(ui = ui, server = server)

The imola::gridPage was in the original code but that did not yield the result showed in the video. So, I tried the fluidPage with tags$style, but it still does not show the intended result. Here's what it looks like:

enter image description here

How can I achieve the goal of putting all filters in a single, continuous line?

CodePudding user response:

The trick is to use css to get it done, here is an example.

  1. I put all the inputs in a single container with display: flex;. Nother option is to add display: inline; to each element.

  2. Change the style each select input: remove border.

library(shiny)

ui <- fluidPage(
  div(
    id = "input-container",
    span("Cars with"),
    selectInput("am", label = NULL, choices = c("manual" = 0, "automatic" = 1), width = "100px"),
    span("transmission and"),
    selectInput("cyl", label = NULL, choices = unique(mtcars$cyl), width = "50px"),
    span("cylinders")
  ),
  tableOutput("table"),
  tags$style(
    "
    #input-container {
      display: flex;
      gap: 3px;
    }
    .selectize-input {
      border: 0;
      padding: 0 10px;
    }
    "
    )
  
)

server <- function(input, output, session) {
  output$table <- renderTable({
    mtcars[mtcars$cyl == input$cyl & mtcars$am == input$am, ]
  })
}

shinyApp(ui, server)

enter image description here

  • Related