Mwavu
Mwavu

Mwavu

Customize Selectize Input In R Shiny

Photo by Shubham Dhage on Unsplash

Customize Selectize Input In R Shiny

Add a remove button, set max items user can select, change height.

Mwavu's photo
Mwavu
·Mar 7, 2022·

5 min read

Table of contents

  • Add Remove Button
  • Set Max Items
  • Change Height Of Selectize List
  • A Sample Application
  • DRY?

Let's not beat around the bush here, shiny's default selectInput() and selectizeInput() come with a few nice functionalities which you might find useful. But sometimes you may wish to tweak them a little to suite some specific needs.

After a little thinking you decide to start with the usual ?selectInput to view shiny's documentation. Under options arg they hit you with the:

... See documentation of selectize.js for possible options...

When I was a beginner in shiny nothing used to scare me more than being referred to a JavaScript library. Which is probably why you're reading this in the first place... You're scared, aren't you?

So, what are we going to discuss?

  • Add remove button to each selected item
  • Set maximum items user can select
  • How to change the height of selectize list
  • Complete app example
  • DRY?

Most of these tips come in handy especially when you've set the argument multiple = TRUE and they're super easy to implement. Alright, let's diiive right in!

Add Remove Button

image.png

The default selectizeInput() looks something like this:

library(shiny)

ui <- fluidPage(
  selectizeInput(
    inputId = "defaultSelectizeInput",
    label = "Default Selectize Input",
    choices = LETTERS,
    selected = LETTERS[1:10],
    multiple = TRUE
  )
)

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

}

shinyApp(ui, server)

That's just okay, but my main issue is how is a user supposed to know that after making a selection they can tap on their backspace to delete it? According to me it's supposed to be more obvious than that.

To add that functionality all you have to do is add this little code chunk to your selectizeInput():

options = list(
      plugins = list("remove_button")
    )

So our initial selectizeInput() now becomes:

selectizeInput(
    inputId = "removeButton",
    label = "Selectize Input with Remove",
    choices = LETTERS,
    selected = LETTERS[1:10],
    multiple = TRUE,
    # ----this:----
    options = list(
      plugins = list("remove_button")
    )
  )

And Voila! If you want to see more magic stick with me to the end.

Set Max Items

choice-paradox.jpg

After seeing what we did above you can already guess what this part will look like. All we want to do is make sure the user doesn't select more than 4 items (I chose 4 because why not!).

You just have to add this code inside your selectizeInput():

selectizeInput(
    inputId = "setMaxItems",
    label = "You can only choose 4",
    choices = LETTERS,
    selected = LETTERS[1:10],
    multiple = TRUE,
    # ----this:----
    options = list(
      maxItems = 4
    )
  )

Change Height Of Selectize List

image.png

By default selectizeInput() will list around 7-8 options on the screen if your choices are many. This might be too many or too few for your liking. So how do you add or reduce the number of choices displayed? Easy peasy!

You just have to add this piece of code anywhere in your shiny app body:

# Reduce height of selectize input:
tags$style(
        type='text/css', ".selectize-dropdown-content {max-height: 100px; }"
      )
# Alter the max-height to your liking!

Note:

  • Setting this changes the height of every selectizeInput in your app. (Sorry, did you shoot yourself on the foot? Maybe.)*
  • If you're using shinydashboard, place that piece of code anywhere inside dashboardBody().

A Sample Application

Now to combine all the above:

library(shiny)

ui <- fluidPage(
  tags$style(
    type='text/css', ".selectize-dropdown-content {max-height: 100px; }"
  ),

  selectizeInput(
    inputId = "shorterSelectizeList",
    label = "Shorter height selectize input",
    choices = LETTERS,
    selected = LETTERS[1:10],
    multiple = TRUE, 
    options = list(
      plugins = list("remove_button")
      maxItems = 4
    )
  )
)

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

}

shinyApp(ui, server)

DRY?

image.png

So far so good, right? Right. But Mwavu, R gurus like Hadley Wickham emphasize the DRY principle (Don't Repeat Yourself). Setting those options on every selectizeInput() is kinda wet... Yunno, not dry. (God, I'm so funny. Ha. Ha.) How do you avoid that? Simple. Use a function.

selectizeOptions <- function(n = NULL) {
  if (!is.null(n)) {
    return(
      list(
        'plugins' = list('remove_button'),
        maxItems = n
      )
    )
  }

  list(
    'plugins' = list('remove_button')
  )
}

What does the above function do?

  1. Checks if you have supplied the argument n (max items user can select). If yes, it adds two functionalities to your selectizeInput: Adds an x beside each selected option which when pressed deselects the option & max number of items user can select.

  2. If n isn't given, it adds only one functionality to your selectizeInput: Adds an x beside each selected option which when pressed deselects the option.

How do we use the function in an application? Call it in the selectizeInput()s you want to customize. I have a small reprex app below:

library(shiny)
library(shinydashboard)

selectizeOptions <- function(n = NULL) {
  if (!is.null(n)) {
    return(
      list(
        'plugins' = list('remove_button'),
        maxItems = n
      )
    )
  }

  list(
    'plugins' = list('remove_button')
  )
}

ui <- dashboardPage(
  header = dashboardHeader(
    title = "Selectize Input"
  ),

  sidebar = dashboardSidebar(

  ),

  body = dashboardBody(
    tags$style(
      type='text/css', ".selectize-dropdown-content {max-height: 100px; }"
    ),

    selectizeInput(
      inputId = "steroidSelectizeInput",
      label = "selectizeInput on steroids!",
      choices = LETTERS,
      selected = LETTERS[1:10],
      multiple = TRUE,
      options = selectizeOptions(n = 4)
    )
  )
)

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

}

shinyApp(ui, server)

There are definitely other plugins & extensions you can use to further customize your selectizeInput but those 3 have proved to be the most useful to me.

 
Share this