Get started with shinyfilters

shinyfilters creates shiny inputs for filtering data. This article uses nyc_flights, a sample of flights that left New York City in 2013.

Filters from a data frame

shinyfilters() turns a data frame into a set of filters.

filters <- shinyfilters(nyc_flights)

Printing it shows the input each column gets:

filters
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput

Customizing filters

You can customize these settings on a shinyfilters object:

  • A filter’s input function
  • The values used to create and update the input function
  • Add a namespace

Change a filter’s input function

  • Set an argument of shinyfilters():
shinyfilters(nyc_flights, range = TRUE)
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Use with_defaults():
filters |> with_defaults(range = TRUE)
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Use with_filters():
filters |> with_filters(date = "range")
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   ●  date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>      origin     <fct>   selectizeInput
#>      dest       <chr>   selectizeInput
#>      dep_delay  <dbl>   sliderInput
#>      distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ● Filter set by `with_filters()`


See vignette("shinyfilters-catalog") for the full list of input functions available in shinyfilters.

Change a filter’s arguments

  • Use with_args():
filters |>
    with_args(dep_delay ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>                        value = range(.x, na.rm = TRUE)
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Use with_filters():
filters |>
    with_filters(dep_delay ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>                        value = range(.x, na.rm = TRUE)
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Choose the input and set its arguments together:
filters |>
    with_filters(dep_delay ~ "slider" ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>      date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>      origin     <fct>   selectizeInput
#>      dest       <chr>   selectizeInput
#>   ●  dep_delay  <dbl>   sliderInput
#>                           value = range(.x, na.rm = TRUE)
#>      distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ● Filter set by `with_filters()`
filters |>
    with_filters(dep_delay ~ sliderInput ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>      date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>      origin     <fct>   selectizeInput
#>      dest       <chr>   selectizeInput
#>   ●  dep_delay  <dbl>   sliderInput
#>                           value = range(.x, na.rm = TRUE)
#>      distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ● Filter set by `with_filters()`


Change multiple filters together

  • Set multiple filters inside with_filters():
filters |>
    with_filters(
        dep_delay ~ list(value = range(.x)),
        distance  = 1.609344 * distance
    )
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>      date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>      origin     <fct>   selectizeInput
#>      dest       <chr>   selectizeInput
#>      dep_delay  <dbl>   sliderInput
#>                           value = range(.x, na.rm = TRUE)
#>   ^  distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ^ Filter replaced by `with_filters()`


Use a namespace

  • Set the ns argument of shinyfilters():
shinyfilters(nyc_flights, ns = "sidebar-mod")
#> <shinyfilters> • 7 filters • namespace "sidebar-mod"
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Use with_ns():
filters |>
    with_ns("sidebar-mod")
#> <shinyfilters> • 7 filters • namespace "sidebar-mod"
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   carrier    <chr>   selectizeInput
#>   origin     <fct>   selectizeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput


Use a non-shiny input function

  • Use a shinyWidgets input in with_filters(). It comes with the function that updates it:
library(shinyWidgets)

filters |>
    with_filters(dest = pickerInput)
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>      date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>      origin     <fct>   selectizeInput
#>   ●  dest       <chr>   pickerInput
#>                           .update_fn = updatePickerInput {shinyWidgets}
#>      dep_delay  <dbl>   sliderInput
#>      distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ● Filter set by `with_filters()`
  • For an input from anywhere else, name the function that updates it with .update_fn:
filters |>
    with_filters(
        origin ~ shiny::checkboxGroupInput ~
            list(.update_fn = shiny::updateCheckboxGroupInput)
    )
#> <shinyfilters> • 7 filters
#> 
#> Filters
#>      date       <date>  dateRangeInput
#>      carrier    <chr>   selectizeInput
#>   ●  origin     <fct>   checkboxGroupInput {shiny}
#>                           .update_fn = updateCheckboxGroupInput {shiny}
#>      dest       <chr>   selectizeInput
#>      dep_delay  <dbl>   sliderInput
#>      distance   <dbl>   sliderInput
#>      delayed    <lgl>   selectizeInput
#> 
#> ● Filter set by `with_filters()`


Selecting filters

After creating your filters, you can select multiple filters or a single filter, allowing you to place the filters anywhere in an application

Select multiple filters

  • Use [:
filters[-c(carrier, origin)]
#> <shinyfilters> • 5 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Use [ with <[tidy-select][tidyselect::language]>:
library(tidyselect)

filters[starts_with("d")]
#> <shinyfilters> • 5 filters
#> 
#> Filters
#>   date       <date>  dateRangeInput
#>   dest       <chr>   selectizeInput
#>   dep_delay  <dbl>   sliderInput
#>   distance   <dbl>   sliderInput
#>   delayed    <lgl>   selectizeInput
  • Select and create with [[:
filters[[c(carrier, origin)]]


Select one filter


  • Use $:
filters$dest


  • Use [[:
filters[["dest"]]


Use in a shiny app

UI

You can place the filters directly inside a UI.

library(bslib)
library(DT)
library(shiny)

ui <- page_sidebar(
    sidebar = sidebar(
        filters
    ),
    DTOutput("data")
)

Organizing

To organize filters, you can select them individually or by group.

library(bslib)
library(DT)
library(shiny)

ui <- page_sidebar(
    sidebar = sidebar(
        filters[date],
        accordion(
            accordion_panel(
                "Airports",
                filters[[c(origin, dest)]]
            ),
            accordion_panel(
                "Time",
                filters[[contains("delay")]]
            ),
            accordion_panel(
                "Other",
                filters[[!c(date, origin, dest, contains("delay"))]]
            )
        )
    ),
    DTOutput("data")
)

Server

In the server, use shinyfilters_server() to enable interdependency:

server <- function(input, output, session) {
    sidebar <- shinyfilters_server(filters)
    output$data <- renderDT(datatable(sidebar$filtered))
}

Run the app

Run the application as you normally would.

shinyApp(ui, server)

Notes

Bookmarking

Apps that use bookmarking need filterInput(filters) inside their UI function instead, so the inputs restore their bookmarked values. Placing filters in their UI directly is an error.

Custom objects

If you’re filtering a custom object, you may need to extend shinyfilters. See vignette("extending-shinyfilters") for details.