3
votes

I have a shiny app containing a server-side selectize input with a long list (>10k) of choices. I would like to update the selection upon clicking a button. Here is a reproducible example

library(shiny)

ui <- fluidPage(
  actionButton('buttonid','Button'),

  selectizeInput("listid", "A long list", choices = NULL)
  )

server <- function(input, output, session) 
  {
  updateSelectizeInput(session, "listid", choices = paste("Item", 1:10000), server = T)
  observeEvent(input$buttonid,
               {
               updateSelectizeInput(session, "listid", selected = "Item 1234")
               })
  }

shinyApp(ui = ui, server = server)

The above code results in a blank selection when I press the button. However, if I search for "Item 1234", then change selection, and press the button, now the item gets selected.

Also, trying to select an item between Item 1 and 1000 does not give problems, presumably because 1000 items get loaded at the beginning.

This seems akin to this old bug, but I am not sure if there is a workaround https://github.com/rstudio/shiny/issues/1018

2
I also sent this as a bug report github.com/rstudio/shiny/issues/2760nico

2 Answers

5
votes

The short answer is explicitly re-specify your choices and server in your update.

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

  myChoices <- paste("Item", 1:10000)

  updateSelectizeInput(session, "listid", choices = myChoices, server = T)
  observeEvent(input$buttonid,
               {
                 updateSelectizeInput(session, "listid",
                                      server = TRUE,
                                      choices = myChoices,
                                      selected = "Item 1234")

               })
}

The default for server in updateSelectizeInput is FALSE. This causes the code to drop into a control statement which uses updateSelectInput instead. From the function code

function (session, inputId, label = NULL, choices = NULL, selected = NULL, 
    options = list(), server = FALSE) 
{
    ...

    if (!server) {
        return(updateSelectInput(session, inputId, label, choices, 
            selected))
    }

   ...

This sends a message to the client assuming all the choices are present (but as you mentioned, only the first 1000 are present).

Just setting server = TRUE results in an error when you click the button.

Warning: Error in [.data.frame: undefined columns selected
  [No stack trace available]

I didn't fully trace the reason, but it ultimately creates an empty choices data.frame with an attribute denoting the selected value. I'm guessing somewhere else in function calls to the session object, this attribute is being used to try to select a column created from the empty data.frame.

The update function doesn't seem to change the choices stored on the server, so that's presumably why it's there when you search for it. During the changing the selected value, it seems to be trying to select from a NULL list of choices instead of the list of choices on the server.

It seems like you essentially have to recreate your selectizeInput when updating with a selected value beyond your initial list.

3
votes

You can use maxOptions to render all values, might be enough depending on the size of your choices:

selectizeInput("listid", "A long list", choices = NULL, options = list(maxOptions = 10000))