Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reactive selectizeInput box fail to update correctly in Shiny 1.8.0, first value of previous allowed choices are kept #3966

Closed
Roleren opened this issue Jan 9, 2024 · 8 comments · Fixed by #3967 or #4142

Comments

@Roleren
Copy link

Roleren commented Jan 9, 2024

System details

Browser Version:

Output of sessionInfo():

R version 4.3.0 (2023-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Ubuntu 22.04.3 LTS

Matrix products: default
BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C               LC_TIME=nb_NO.UTF-8        LC_COLLATE=en_US.UTF-8     LC_MONETARY=nb_NO.UTF-8   
 [6] LC_MESSAGES=en_US.UTF-8    LC_PAPER=nb_NO.UTF-8       LC_NAME=C                  LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=nb_NO.UTF-8 LC_IDENTIFICATION=C       

time zone: Europe/Oslo
tzcode source: system (glibc)

attached base packages:
[1] stats4    stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] DT_0.30                     shiny_1.8.0                 fstcore_0.9.14              data.table_1.14.8          
 [5] RiboCrypt_1.5.1             ORFik_1.23.5                GenomicAlignments_1.36.0    Rsamtools_2.16.0           
 [9] Biostrings_2.69.2           XVector_0.40.0              SummarizedExperiment_1.30.1 Biobase_2.60.0             
[13] MatrixGenerics_1.12.3       matrixStats_1.2.0           GenomicRanges_1.52.0        GenomeInfoDb_1.36.1        
[17] IRanges_2.34.1              S4Vectors_0.38.1            BiocGenerics_0.46.0        

loaded via a namespace (and not attached):
  [1] RColorBrewer_1.1-3      shape_1.4.6             rstudioapi_0.14         jsonlite_1.8.4          magrittr_2.0.3         
  [6] shinyjqui_0.4.1         GenomicFeatures_1.52.0  rmarkdown_2.21          fs_1.6.2                GlobalOptions_0.1.2    
 [11] BiocIO_1.10.0           zlibbioc_1.46.0         vctrs_0.6.2             NGLVieweR_1.3.1         memoise_2.0.1          
 [16] RCurl_1.98-1.12         usethis_2.1.6           htmltools_0.5.5         S4Arrays_1.2.0          progress_1.2.2         
 [21] curl_5.0.0              sass_0.4.6              bslib_0.5.1             fontawesome_0.5.1       htmlwidgets_1.6.2      
 [26] plotly_4.10.1           cachem_1.0.8            mime_0.12               lifecycle_1.0.3         iterators_1.0.14       
 [31] pkgconfig_2.0.3         Matrix_1.6-4            R6_2.5.1                fastmap_1.1.1           clue_0.3-64            
 [36] GenomeInfoDbData_1.2.10 digest_0.6.31           colorspace_2.1-0        ps_1.7.5                shinycssloaders_1.0.0  
 [41] AnnotationDbi_1.62.1    DESeq2_1.40.1           pkgload_1.3.2           crosstalk_1.2.0         RSQLite_2.3.1          
 [46] filelock_1.0.2          fansi_1.0.4             httr_1.4.5              abind_1.4-5             compiler_4.3.0         
 [51] remotes_2.4.2           bit64_4.0.5             doParallel_1.0.17       BiocParallel_1.34.0     DBI_1.1.3              
 [56] pkgbuild_1.4.0          R.utils_2.12.2          biomaRt_2.56.0          sessioninfo_1.2.2       rappdirs_0.3.3         
 [61] DelayedArray_0.26.1     rjson_0.2.21            tools_4.3.0             httpuv_1.6.9            fst_0.9.8              
 [66] R.oo_1.25.0             glue_1.6.2              callr_3.7.3             restfulr_0.0.15         promises_1.2.0.1       
 [71] grid_4.3.0              cluster_2.1.4           generics_0.1.3          gtable_0.3.3            BSgenome_1.68.0        
 [76] R.methodsS3_1.8.2       tidyr_1.3.0             hms_1.1.3               xml2_1.3.4              utf8_1.2.3             
 [81] markdown_1.6            foreach_1.5.2           pillar_1.9.0            stringr_1.5.0           later_1.3.1            
 [86] circlize_0.4.15         dplyr_1.1.2             BiocFileCache_2.8.0     lattice_0.21-8          rtracklayer_1.60.0     
 [91] bit_4.0.5               tidyselect_1.2.0        ComplexHeatmap_2.16.0   locfit_1.5-9.7          miniUI_0.1.1.1         
 [96] knitr_1.42              gridExtra_2.3           xfun_0.39               devtools_2.4.5          stringi_1.7.12         
[101] lazyeval_0.2.2          yaml_2.3.7              evaluate_0.20           codetools_0.2-19        tibble_3.2.1           
[106] cli_3.6.1               xtable_1.8-4            processx_3.8.1          munsell_0.5.0           jquerylib_0.1.4        
[111] biomartr_1.0.8.9000     Rcpp_1.0.10             dbplyr_2.3.2            png_0.1-8               XML_3.99-0.14          
[116] parallel_4.3.0          ellipsis_0.3.2          shinyhelper_0.3.2       ggplot2_3.4.2           rclipboard_0.2.0       
[121] blob_1.2.4              prettyunits_1.1.1       profvis_0.3.8           urlchecker_1.0.1        bitops_1.0-7           
[126] viridisLite_0.4.2       scales_1.2.1            purrr_1.0.1             crayon_1.5.2            GetoptLong_1.0.5       
[131] rlang_1.1.1             cowplot_1.1.1           KEGGREST_1.40.0         shinyjs_2.1.0          

Example application or steps to reproduce the problem

library(shiny)
ui <- fluidPage(
  titlePanel(tag("u", "Test"), "Test"),
  selectizeInput(
    inputId = "selectID",
    label = "Select id type",
    choices = c("Numeric", "Letters"),
    selected = "Numeric",
    multiple = FALSE
  ),
  selectizeInput(
    inputId = "library",
    label = "Select libraries",
    choices = as.character(seq(5)),
    selected = 1,
    multiple = TRUE
  ),
  h3("And now!?"),
  br(),
)
server <- function(input, output, session) {

  observeEvent(input$selectID, {
    if (input$selectID == "Numeric") {
      choices <- as.character(seq(5))
    } else {
      choices <- LETTERS[1:5]
    }
    updateSelectizeInput(
      inputId = "library",
      choices = choices,
      selected = choices[1],
      server = TRUE
    )

  },
               ignoreNULL = TRUE, ignoreInit = FALSE)
  session$onSessionEnded(function() { stopApp() })
}
print(shinyApp(ui, server, options = list(launch.browser = TRUE)))

Describe the problem in detail

A new bug in 1.8.0, I can verify that this does not happen in 1.7.4, which I had before I updated today.

When you have a box (library) with selectable numbers 1,2,3,4,5 and another box (selectID) that defines id type of box (library) (numeric is default or character: i.e. changes the selection in (library) to A,B,C,D,E.
The total allowed selection of (library) will not be A,B,C,D,E, but 1,A,B,C,D,E.
If you flip back to numeric, the allowed options are then: A,1,2,3,4,5

Even though you restrict the types on updateSelectizeInput, this is clearly ignored as the first value of previous allowed choices are kept

This breaks our app on www.Ribocrypt.org

gadenbuie added a commit that referenced this issue Jan 9, 2024
@gadenbuie
Copy link
Member

Hi @Roleren, thanks for the bug report!

One important detail: this only happens when server = TRUE. In this case, the full set of choices are kept back on the server because they could be potentially large and are only sent to the client app when requested. If you completely change the available choices, the client won't know that the current (about to be old) values are no longer valid, so it keeps those values as options.

We can do slightly better than the current situation when selected is provided. I've just added a bit of code in #3967 that will clear the current value of the select input before performing the choices update when selected is provided.

Here are two other options to get around this issue with released shiny:

  1. Use fully client-side selectize inputs, i.e. server = FALSE.

  2. Manually clear the selection before updating the choices and current value, but having an observeEvent() that first clears the selection:

    choices <- reactive({
      if (input$selectID == "Numeric") {
        as.character(seq(5))
      } else {
        LETTERS[1:5]
      }
    })
    
    observeEvent(choices(), {
      # Clear the selection before updating choices
      updateSelectizeInput(
        inputId = "library",
        selected = NULL,
        server = TRUE
      )
    })
    
    observeEvent(choices(), {
      updateSelectizeInput(
        inputId = "library",
        choices = choices(),
        selected = choices()[1],
        server = TRUE
      )
    })

@Roleren
Copy link
Author

Roleren commented Jan 9, 2024

Thanks, this should solve the issue for now. As far as I understand, the old value is still kept if selected is not specified ?

cpsievert added a commit that referenced this issue Mar 14, 2024
…cted` and `sever = TRUE` (#3967)

* fix(updateSelectizeInput): Clear current value before update if `selected` and `server = TRUE`

Fixes #3966

* chore: yarn build

* `yarn build` (GitHub Actions)

* docs(news): Add news item

* chore: Add comments for future selves

Co-authored-by: Carson Sievert <[email protected]>

* `yarn build` (GitHub Actions)

---------

Co-authored-by: gadenbuie <[email protected]>
Co-authored-by: Carson Sievert <[email protected]>
@trangdata
Copy link

I'm not sure if #3967 fixed this. I'm still having the same issue as explained in the original post with shiny v1.8.1.1 and development version.

@gadenbuie
Copy link
Member

@trangdata I just tried the reprex in the original post with shiny v1.8.1.1 and it worked for me as expected after #3967. If you're encountering a similar issue it might actually be a new or different problem. Can you please open a new issue with a reproducible example so we can take a look?

@trangdata
Copy link

trangdata commented Jul 10, 2024

I ran the same reprex with shiny v1.8.1.1. Maybe I can clarify what I see a little bit:

When I first load the app, I have Numeric. I select libraries 1, 3, 5, then switch to Letters. Now, the selected library is A. However, when I click on the input box to select more libraries (expectedly only letters), I see 1, 3, 5 as options also.

Maybe I'm missing something obvious?!

@gadenbuie
Copy link
Member

gadenbuie commented Jul 10, 2024

I don't think it's that you missed something obvious, I had to re-read the issue again carefully to remember...

When I first load the app, I have Numeric. I select libraries 1, 3, 5, then switch to Letters. Now, the selected library is A. However, when I click on the input box to select more libraries (expectedly only letters), I see 1, 3, 5 as options also.

This part of the issue isn't fixed by #3967, because

when server = TRUE ... the full set of choices are kept back on the server because they could be potentially large and are only sent to the client app when requested. If you completely change the available choices, the client won't know that the current (about to be old) values are no longer valid, so it keeps those values as options.

My recommendation for solving this part of the problem was to

Manually clear the selection before updating the choices and current value, but having an observeEvent() that first clears the selection

by adding the following to the server logic above the observeEvent() that sets the new selection and choices.

observeEvent(choices(), {
  # Clear the selection before updating choices
  updateSelectizeInput(
    inputId = "library",
    selected = NULL,
    server = TRUE
  )
})

@trangdata
Copy link

Ah okay! Thank you for clarifying Garrick! I saw your workaround in the earlier comment but thought that #3967 fixed everything and I would not have to manually clear the selection before updating the choices. But it makes sense now. Thanks!

@dvg-p4
Copy link
Contributor

dvg-p4 commented Oct 9, 2024

This is actually a bug in selectize.js, you can observe similar behavior on https://selectize.dev/docs/demos/api. I've filed a ticket there: selectize/selectize.js#2146

dvg-p4 added a commit to dvg-p4/shiny that referenced this issue Oct 10, 2024
gadenbuie added a commit that referenced this issue Dec 6, 2024
* Work around a selectize bug (re-fixes #3966)

---------

Co-authored-by: Garrick Aden-Buie <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants