Noskario
Noskario

Reputation: 674

How can I adapt the behaviour of selectizeInput to be more similar to selectInput?

I want for my shiny-app, that when the user deletes the entry in a selectizeInput, that the app does not react at all, just like it happens with selectInput. Also when the empty selectizeInput looses focus, I want that the former value is restored, just like with selectInput.

However, I do not want to use selectInput in my app because I already have a lot of CSS that does not work quiet as well with selctInput. Also I use some of the selectize-plugins from time to time. So my question is: How can I achieve my two desired behaviours (as described in the beginning)?

When you compare the code, that selectInput and selectizeInput produce:

> selectInput("selectInput", "labelSelectInput", choices = c("alpha", "beta", "gamma"))

<div class="form-group shiny-input-container">
  <label class="control-label" id="selectInput-label" for="selectInput">labelSelectInput</label>
  <div>
    <select id="selectInput" class="shiny-input-select"><option value="alpha" selected>alpha</option>
<option value="beta">beta</option>
<option value="gamma">gamma</option></select>
    <script type="application/json" data-for="selectInput" data-nonempty="">{"plugins":["selectize-plugin-a11y"]}</script>
  </div>
</div>



> selectizeInput("selectInput", "labelSelectInput", choices = c("alpha", "beta", "gamma"))

<div class="form-group shiny-input-container">
  <label class="control-label" id="selectInput-label" for="selectInput">labelSelectInput</label>
  <div>
    <select class="shiny-input-select form-control" id="selectInput"><option value="alpha" selected>alpha</option>
<option value="beta">beta</option>
<option value="gamma">gamma</option></select>
    <script type="application/json" data-for="selectInput">{"plugins":["selectize-plugin-a11y"]}</script>
  </div>
</div>

you see that the only two differences are that the class of selectizeInput also has a form-control and that in the script of selectizeInput the data-nonempty=""-part is missing. I guess the fact, that it is missing is the problem. However, adding an argument options = list(`data-nonempty`="") is not working.

So maybe there is another way of doing it?

To see the different behaviour, have a look at the following code and pictures:

library(shiny)

ui <- fluidPage(
  fluidRow(
    column(
      6,
      textOutput("selectInputChoice"),
      selectInput(inputId = "selectInputId", label = "label", choices = c("alpha", "beta", "gamma")),
    ),
    column(
      6,
      textOutput("selectizeInputChoice"),
      selectizeInput(inputId = "selectizeInputId", label = "label", choices = c("alpha", "beta", "gamma")),
    )
  )
)

server <- function(input, output, session) {
  output$selectInputChoice <- renderText({
    paste("selectInput:",input$selectInputId)
  })
  output$selectizeInputChoice <- renderText({
    paste("selectizeInput:",input$selectizeInputId)
  })
}

shinyApp(ui, server)

"alpha" still displayed:

select

"" displayed

selectize

Upvotes: 1

Views: 40

Answers (1)

Jan
Jan

Reputation: 9143

That no input change is triggered if the user deletes the entry can be set by having an shiny:inputchanged event listener which returns false if the value of the selectizeInput is "".

The restore of the value if the dropdown gets closed and the input is empty can be implemented by having an onDropdownOpen event which saves the current value if the dropdown gets opened and an onDropdownClose event which sets the value back to the previously stored value.

enter image description here

library(shiny)

ui <- fluidPage(
  tags$head(
    tags$script(
      HTML("$(document).on('shiny:inputchanged', function(e) {
              if (e.name === 'selectizeInputId' && e.value === '') {
                return false;
              }
            });")
    )
  ),
  fluidRow(
  column(
    6,
    textOutput("selectInputChoice"),
    selectInput(
      inputId = "selectInputId",
      label = "label",
      choices = c("alpha", "beta", "gamma")
    ),
  ),
  column(
    6,
    textOutput("selectizeInputChoice"),
    selectizeInput(
      inputId = "selectizeInputId",
      label = "label",
      choices = c("alpha", "beta", "gamma"),
      options = list(
        onDropdownOpen = I('function() { value = this.getValue() }'),
        onDropdownClose = I('function() {
                               if (this.getValue() === "") {
                                 this.setValue(value);
                               }
                             }')
      )
    )
  )
))

server <- function(input, output, session) {
  output$selectInputChoice <- renderText({
    paste("selectInput:", input$selectInputId)
  })
  output$selectizeInputChoice <- renderText({
    paste("selectizeInput:", input$selectizeInputId)
  })
}

shinyApp(ui, server)

Upvotes: 1

Related Questions