order of initial value is not preserved by selectInput
For instance consider the following code:
selectInput("myInput", "myInput", multiple = TRUE,
choices = c("a", "b", "c"),
selected = c("b", "a"))
When the shiny server starts, the value of "myInput" will be c("a", "b") instead of c("b", "a"). This can be a problem if the order of the selected elements matters.
A solution could be to store the initial value in a dedicated html attribute, for instance:
<select id="myInput" multiple="multiple" data-init-values="b,a">
...
</select>
Along these same lines, it would be useful to have the choices respect factor levels:
library(shiny)
lvls <- c("b", "c", "a")
f1 <- factor(c("a", "b", "c"), levels = lvls)
ui <- fluidPage(
selectizeInput(
"d", "asdfas", choices = f1, multiple = TRUE
)
)
server <- function(input, output) {}
shinyApp(ui, server)
Do you know if this has been solved without any "workaround" ?
I just stumbled upon the same issue. My workaround for anyone that runs into the same bug:
selectizeInput("orderBug",
"Order bug",
choices = c("A", "B"),
multiple = TRUE,
options = list(
# multiple issues in Shiny that I had to overcome here:
# 1) order of items provided in "selected" not respected: https://github.com/rstudio/shiny/issues/1490
# 2) I() used to avoid auto-unboxing values in jsonlite::toJSON() overwritten by Shiny
# to instead interpret character strings as JS code. Thus, we fall back to converting
# to a list instead.
items = as.list(c("B", "A")),
)
Note that the as.list() is required if the selected choices is a length-1 character vector as shiny seems to use the auto_unbox option of jsonlite resulting in them being converted to JS strings instead of a length-1 array. We can't use the base::I() function recommended by jsonlite as this is already used by Shiny in this context to interpret strings as JS code (not sure why they don't use htmlwidgets::JS() function here).
We've written a simple selectInput wrapper/drop-in replacement that preserves order selection during initialization as well as bookmark restoration. Code. Short blog post.
The solution is not far away from @fproske's, except that we pass the selection through the onInitialize selectize hook instead. That allows us to sidestep JSON serialization pitfalls. We also call shiny::restoreInput to preserve bookmarking.