I think this is expected behaviour as per the documentation, although perhaps the wording of the documentation is subject to criticism.
It states:
selected
The initially selected value (or multiple values if multiple = TRUE). If not specified then defaults to the first value for single-select lists and no values for multiple select lists.
Since the default argument is NULL this qualifies as not specified and hence the result is expected. However you could argue that it should really say that if NULL this happens.
An alternative solution to the initialise as NULL problem, although perhaps not a satisfactory one, is to set multiple = TRUE
. As stated in the documentation this will select no values for multiple select lists.
EDIT:
A further, maybe more satisfying solution should you find the need to do this a lot is to redefine selectInput
.
myselectInput = function (inputId, label, choices, selected = NULL, multiple = FALSE,
selectize = TRUE, width = NULL, size = NULL)
{
selected <- restoreInput(id = inputId, default = selected)
choices <- shiny:::choicesWithNames(choices)
if (!is.null(selected)) {
selected <- as.character(selected)
}
if (!is.null(size) && selectize) {
stop("'size' argument is incompatible with 'selectize=TRUE'.")
}
selectTag <- tags$select(id = inputId, class = if (!selectize)
"form-control", size = size,
if(is.null(selected))
HTML("<option style = 'display:none;' value disabled selected></option>")
else HTML(""),
shiny:::selectOptions(choices, selected))
if (multiple)
selectTag$attribs$multiple <- "multiple"
res <- div(class = "form-group shiny-input-container", style = if (!is.null(width))
paste0("width: ", validateCssUnit(width), ";"), shiny:::controlLabel(inputId,
label), div(selectTag))
if (!selectize)
return(res)
shiny:::selectizeIt(inputId, res, NULL, nonempty = !multiple && !("" %in%
choices))
}
ui = fluidPage(
myselectInput("ins","IN",selected = NULL, choices = c(letters[1:3]),selectize = FALSE),
textOutput("out")
)
server = function(input,output,session){
observe({
print(is.null(input$ins))
})
}
shinyApp(ui,server)
Most of this is similar to the source of selectInput
apart from
if(is.null(selected))
HTML("<option style = 'display:none;' value disabled selected></option>")
else HTML(""),
and
if (!is.null(selected)) {
selected <- as.character(selected)
}
This will display empty by default, and not allow you to choose empty once deselected. When selectize=FALSE
this also returns a NULL. Curiously when selectize=TRUE
the appearance is the same, but the return is not NULL. I don't know why this is though.