selectizeInputs can lose their bookmarked values on restoration
When an application is bookmarked and restored selectizeInputs can lose their values.
An example follows.
ui <- function(request) {
shiny::fluidPage(
shiny::selectizeInput(
"my_selectize",
"Selectize",
character(0L),
multiple = TRUE,
options = list(create = TRUE)
),
shiny::verbatimTextOutput("my_text"),
shiny::bookmarkButton()
)
}
server <- function(input, output, session) {
output$my_text <- shiny::renderPrint(input$my_selectize)
}
shiny::shinyApp(ui, server, enableBookmarking = "url")
Run the application.
In the selectizeInput enter "a,b,", so that the input's value is c("a", "b").
Click "Bookmark...".
Restore the application.
The input's value is NULL but ought to be c("a", "b").
The fault was observed when the browser was Firefox 141.0 (64-bit) and sessionInfo() was as follows.
R version 4.3.3 (2024-02-29)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 24.04.2 LTS
Matrix products: default
BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
locale:
[1] LC_CTYPE=en_GB.UTF-8 LC_NUMERIC=C
[3] LC_TIME=en_GB.UTF-8 LC_COLLATE=en_GB.UTF-8
[5] LC_MONETARY=en_GB.UTF-8 LC_MESSAGES=en_GB.UTF-8
[7] LC_PAPER=en_GB.UTF-8 LC_NAME=C
[9] LC_ADDRESS=C LC_TELEPHONE=C
[11] LC_MEASUREMENT=en_GB.UTF-8 LC_IDENTIFICATION=C
time zone: Europe/London
tzcode source: system (glibc)
attached base packages:
[1] stats graphics grDevices datasets utils methods base
loaded via a namespace (and not attached):
[1] compiler_4.3.3 tools_4.3.3 renv_1.1.5
Seems important to note that this is only an issue when options = list(create = TRUE) is specified?
@cpsievert, that seems so.
I think this is expected because the bookmark as far as I remember only restores the inputs. So, when the input widget's UI is initialized with the values the bookmark is able to choose them.
In this case the selectize Input dynamically changes the input choices which is out of the scope of the bookmark restore (as it is only meant to restore inputs, not choices).
The workaround I would recommend is to use onRestore to update the choices too:
library(shiny)
ui <- function(request) {
shiny::fluidPage(
shiny::selectizeInput(
"my_selectize",
"Selectize",
character(0L),
multiple = TRUE,
options = list(create = TRUE)
),
shiny::verbatimTextOutput("my_text"),
shiny::bookmarkButton()
)
}
server <- function(input, output, session) {
output$my_text <- shiny::renderPrint(input$my_selectize)
onRestore(function(state) {
updateSelectizeInput(
session,
"my_selectize",
selected = state$input$my_selectize,
choices = state$input$my_selectize
)
})
}
shiny::shinyApp(ui, server, enableBookmarking = "url")
@vedhav, thank you for your reply.
I think this is expected
I did not expect it, and it seems to me to be a bug: the selectizeInput, and everything downstream in the reactive graph of the application, ought to be the same after restoration.
@vedhav, thank you for the work-around. However, if persist = FALSE the state of the selectizeInput differs after restoration.
ui <- function(request) {
shiny::fluidPage(
shiny::selectizeInput(
"my_selectize",
"Selectize",
character(0L),
multiple = TRUE,
options = list(create = TRUE, persist = FALSE)
),
shiny::verbatimTextOutput("my_text"),
shiny::bookmarkButton()
)
}
server <- function(input, output, session) {
output$my_text <- shiny::renderPrint(input$my_selectize)
shiny::onRestore(
function(state) {
shiny::updateSelectizeInput(
session,
"my_selectize",
selected = state$input$my_selectize,
choices = state$input$my_selectize
)
}
)
}
shiny::shinyApp(ui, server, enableBookmarking = "url")
Run the application; enter "a,b,c," in the selectizeInput; click the bookmark button; copy the link.
Now, in the original application if "c" is deleted it is not suggested.
But in the restored application
if "c" is deleted it is suggested.
So the application is not restored exactly.
If that is what you really want, you can achieve this by storing the choices state which can be referenced during the bookmark restore.
library(shiny)
ui <- function(request) {
shiny::fluidPage(
shiny::selectizeInput(
"my_selectize",
"Selectize",
character(0L),
multiple = TRUE,
options = list(create = TRUE, persist = FALSE)
),
shiny::verbatimTextOutput("my_text"),
shiny::bookmarkButton()
)
}
server <- function(input, output, session) {
output$my_text <- shiny::renderPrint(input$my_selectize)
my_selectize_choices <- reactiveVal()
observeEvent(input$my_selectize, {
my_selectize_choices(unique(c(input$my_selectize, my_selectize_choices())))
})
shiny::onBookmark(
function(state) {
state$values$my_selectize_choices <- my_selectize_choices()
}
)
shiny::onRestore(
function(state) {
shiny::updateSelectizeInput(
session,
"my_selectize",
selected = state$input$my_selectize,
choices = state$values$my_selectize_choices
)
}
)
}
shiny::shinyApp(ui, server, enableBookmarking = "url")
@vedhav, thank you, but that does not work: the behaviour is the same as before. However, I have worked around the bug differently.
I don't understand how you get the same behaviour as before. Isn't this what you expected? Can you elaborate on what you expected and what failed? It will be helpful for someone else trying to achieve the same thing.
https://github.com/user-attachments/assets/f414c554-f896-433e-aafa-06e6a2e48726