The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
This guide converts an existing app without changing its downstream code. The filter logic stays identical; only the input construction and the update calls change. The one trap that breaks migrations is the empty-selection default — it is covered first, because it decides the rest.
Native Shiny and glasstabs disagree about the starting state:
| Control | selected = NULL means |
|---|---|
selectInput(multiple = TRUE) |
Nothing selected |
glassMultiSelect() |
Every enabled choice selected |
A migration that copies selected = NULL across changes
the app’s initial filter from “nothing” to “everything.” Decide which
behavior the app had, and write it explicitly — do not let the default
decide for you. The behavior-preserving migration below uses
selected = character(0) to keep the native empty start.
Before, with native Shiny:
library(shiny)
regions <- c(North = "north", South = "south", East = "east")
data <- data.frame(
region = c("north", "south", "east", "north"),
cases = c(12, 8, 5, 3)
)
ui <- fluidPage(
selectInput(
"region",
"Region",
choices = regions,
multiple = TRUE,
selected = NULL
),
tableOutput("rows")
)
server <- function(input, output, session) {
output$rows <- renderTable({
data[data$region %in% input$region, , drop = FALSE]
})
}
shinyApp(ui, server)After, with glasstabs. The downstream filter is untouched:
library(shiny)
library(glasstabs)
regions <- c(North = "north", South = "south", East = "east")
data <- data.frame(
region = c("north", "south", "east", "north"),
cases = c(12, 8, 5, 3)
)
ui <- fluidPage(
useGlassTabs(),
glassMultiSelect(
"region",
choices = regions,
label = "Region",
selected = character(0),
theme = "auto"
),
tableOutput("rows")
)
server <- function(input, output, session) {
output$rows <- renderTable({
data[data$region %in% input$region, , drop = FALSE]
})
}
shinyApp(ui, server)The example above is complete: it defines its dataset, both app halves, and the app object, so it runs end to end.
Two changes beyond the widget swap: useGlassTabs() once
at the UI root (the one rule), and selected = character(0)
preserving the native empty start. If the app actually wants the
glasstabs default (all enabled selected), drop the selected
argument and keep the filter — but then say so in the filter’s comments,
because the next reader will otherwise assume the native default.
For a single-select the swap is selectInput() (without
multiple = TRUE) to glassSelect(), with the
same useGlassTabs() addition. The cleared state of a
single-select returns NULL in both worlds, so no default
trap applies there.
| Native | glasstabs | Notes |
|---|---|---|
updateSelectInput(session, id, choices, selected) |
updateGlassMultiSelect(session, id, choices, selected, ...)
or
updateGlassSelect(session, id, choices, selected, ...) |
Choose by widget, not by the old call |
updateSelectizeInput(session, id, choices, selected) |
Same as above | Server-side selectize becomes server = TRUE + the
*Server() helper, not an update call |
label argument on the native updaters |
No equivalent | The glasstabs updaters take no label; a label change
means recreating the widget with renderUI() |
selected = NULL (keep) |
selected = NULL (keep) |
Same meaning on both sides for updates |
selected = character(0) (clear) |
selected = character(0) (clear) |
Same meaning on both sides for updates |
The update semantics that have no native counterpart are the
transaction options: preserve_selection,
drop_invalid, and notify on the multi-select
updater (see the linked-filters article). A migration that passes only
choices and selected behaves like the native
updater; the extra options are opt-in.
Be candid about the gaps before migrating a selectize-heavy app:
options = list(create = TRUE)): no equivalent. glasstabs
choices come from the app, not the user.options = list(plugins = ...)): no equivalent — no
drag-and-drop sorting, no remove-button plugin (tag pills have their own
remove affordance, but it is not the plugin).server = TRUE plus
a *Server() helper with bounded results. The user-visible
behavior is close, but the code is not interchangeable.<select> with no
JavaScript enhancement (for example, a no-JS fallback page).For everything else — searchable dropdowns, multi-select filters,
themed dashboards, server-backed large lists — the migration above is
the whole job: swap the constructor, add useGlassTabs(),
pin the initial selection explicitly, and remap the update calls.
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.