简体   繁体   中英

Resetting selectInput to NULL in R Shiny

I need to be able to reset several selectInput widgets in R Shiny back to their original value of NULL (with a blank text region in the widget). So far, I'm getting the user input (which variable to use as the x axis) like this:

  output$descrxaxis_Variable <- renderUI({
  selectInput(inputId = "descrxaxis", label = "Choose x axis variable", choices = colnames(descrDataMelted_selVars$df), multiple = TRUE)})

I'm getting the column index of that variable using this:

 x_ind <- reactiveValues(val = NULL)
observeEvent(input$descrxaxis, {
  x_ind$val <- which(colnames(descrDataMelted_selVars$df) == input$descrxaxis)})

What I need to be able to do is reset x_ind to NULL, so that when the user clicks a "Reset X axis" button, the column they previously chose is gone. Here is my current code for doing this:

    observeEvent(input$descrXaxisResetBtn, {
    updateSelectInput("descrxaxis", label = "Choose x axis variable", choices = colnames(descrDataMelted_selVars$df), multiple = TRUE, selected = NULL)})

But, I've also tried:

  observeEvent(input$descrXaxisResetBtn, {
    shinyjs::useShinyjs()
    shinyjs::reset("descrxaxis")})

Neither of these have worked, and the previous variable they chose remains in the widget text box. How do I get this to work? Thank you.

EDIT: Here is the code that works (with the help of those who answered my question).

ui <- navbarPage(title = "SD Mesonet Quality Control", id = "navbarPage",
                     tabPanel(title = 'Metadata',
                              sidebarLayout(
                                sidebarPanel(width = 2,
                                             h4("Select Summary Variables to Plot"),
                                             div(style="display: inline-block; vertical-align:bottom; position:relative",
                                                 fluidRow(
                                                   column(10,
                                                          uiOutput("descrxaxis_Variable")),
                                                   column(2,
                                                          actionButton(inputId = "descrXaxisResetBtn", label = "Reset X", style = "padding:17px; color: #fff; background-color: #337ab7; border-color: #2e6da4"))
                                                 )
                                             ),        
                                             div(style="display: inline-block; vertical-align:bottom; position:relative",
                                                 fluidRow(
                                                   column(10,
                                                          uiOutput("descryaxis_Variable")),
                                                   column(2,
                                                          actionButton(inputId = "descrYaxisResetBtn", label = "Reset Y", style = "padding:17px; color: #fff; background-color: #337ab7; border-color: #2e6da4"))
                                                 )
                                             ),           
                                             div(style="display: inline-block; vertical-align:bottom; position:relative",
                                                 fluidRow(
                                                   column(10,
                                                          uiOutput("descrfacet_Variable")),
                                                   column(2,
                                                          actionButton(inputId = "descrFacetResetBtn", label = "Reset Facet", style = "padding:17px; color: #fff; background-color: #337ab7; border-color: #2e6da4"))
                                                 )
                                             ),        
                                             div(style="display: inline-block; vertical-align:bottom; position:relative",
                                                 fluidRow(
                                                   column(10,
                                                          uiOutput("descrcolor_Variable")),
                                                   column(2,
                                                          actionButton(inputId = "descrColorResetBtn", label = "Reset Color", style = "padding:17px; color: #fff; background-color: #337ab7; border-color: #2e6da4"))
                                                 )
                                             ),
                                             br(),
                                             actionButton("descrBtnPlot","Plot", style="color: #fff; background-color: #337ab7; border-color: #2e6da4")
                                             
                                ),
                                mainPanel(width = 10,
                                          plotlyOutput("descrSummaryStatsPlot")
                                )
                              )
                     )
    )
    
    server <- function(input,output,session){
      output$descrxaxis_Variable <- renderUI({
        selectInput(inputId = "descrxaxis", label = "Choose x axis variable", choices = colnames(descrDataMelted_selVars), multiple = TRUE, selected = character(0))})
      
      output$descryaxis_Variable <- renderUI({
        selectInput(inputId = "descryaxis", label = "Choose y axis variable", choices = colnames(descrDataMelted_selVars), multiple = TRUE)})
      
      output$descrfacet_Variable <- renderUI({
        selectInput(inputId = "descrfacet", label = "Choose facet variable", choices = colnames(descrDataMelted_selVars), multiple = TRUE)})
      
      output$descrcolor_Variable <- renderUI({
        selectInput(inputId = "descrcolor", label = "Choose color variable", choices = colnames(descrDataMelted_selVars), multiple = TRUE)})
      
      x_ind <- reactiveValues(val = NULL)
      observeEvent(input$descrxaxis, {
        x_ind$val <- which(colnames(descrDataMelted_selVars) == input$descrxaxis)})
      
      y_ind <- reactiveValues(val = NULL)
      observeEvent(input$descryaxis, {
        y_ind$val <- which(colnames(descrDataMelted_selVars) == input$descryaxis)})
      
      facet_ind <- reactiveValues(val = NULL)
      observeEvent(input$descrfacet, {
        facet_ind$val <- which(colnames(descrDataMelted_selVars) == input$descrfacet)})
      
      color_ind <- reactiveValues(val = NULL)
      observeEvent(input$descrcolor, {
        color_ind$val <- which(colnames(descrDataMelted_selVars) == input$descrcolor)})
      
      observeEvent(input$descrBtnPlot,{
        if (!is.null(x_ind$val) & !is.null(y_ind$val) & is.null(facet_ind$val) & is.null(color_ind$val)){
          p <- ggplot(descrDataMelted_selVars, aes_string(x = colnames(descrDataMelted_selVars)[x_ind$val], y = colnames(descrDataMelted_selVars)[y_ind$val])) + geom_point()}
        
        if (!is.null(x_ind$val) & !is.null(y_ind$val) & is.null(facet_ind$val) & !is.null(color_ind$val)){
          p <- ggplot(descrDataMelted_selVars, aes_string(x = colnames(descrDataMelted_selVars)[x_ind$val], y = colnames(descrDataMelted_selVars)[y_ind$val],
                                                          color = colnames(descrDataMelted_selVars)[color_ind$val])) + geom_point()}
        
        if (!is.null(x_ind$val) & !is.null(y_ind$val) & !is.null(facet_ind$val) & is.null(color_ind$val)){
          p <- ggplot(descrDataMelted_selVars, aes_string(x = colnames(descrDataMelted_selVars)[x_ind$val], y = colnames(descrDataMelted_selVars)[y_ind$val])) + geom_point() +
            facet_wrap(as.formula(paste("~",colnames(descrDataMelted_selVars)[facet_ind$val])))}
        
        if (!is.null(x_ind$val) & !is.null(y_ind$val) & !is.null(facet_ind$val) & !is.null(color_ind$val)){
          p <- ggplot(descrDataMelted_selVars, aes_string(x = colnames(descrDataMelted_selVars)[x_ind$val], y = colnames(descrDataMelted_selVars)[y_ind$val],
                                                          color = colnames(descrDataMelted_selVars)[color_ind$val])) + geom_point() +
            facet_wrap(as.formula(paste("~",colnames(descrDataMelted_selVars)[facet_ind$val])))}
        
        output$descrSummaryStatsPlot <- renderPlotly(p)
      })
      
      observeEvent(input$descrXaxisResetBtn, {
        updateSelectInput(session,"descrxaxis", selected = character(0))
      })
      
    }
    shinyApp(ui,server)

Up front, use selected=character(0) (or selected="" , as @starja commented):

    updateSelectInput("descrxaxis", label = "Choose x axis variable",
                      choices = colnames(descrDataMelted_selVars$df), multiple = TRUE, 
                      selected = character(0))

Some key components from your other (duplicate) question that need to be fixed, and are relevant to the concept of updating inputs (but not obvious based on the current state of this question):

  • First, do not nest observe or observeEvent within another one. This might be a typo in your code there, but make sure that all observe* (and any reactive function, for that matter) functions are effectively on the "top-level" of the server function.

    Change from

     observeEvent(input$descrBtnPlot,{... output$descrSummaryStatsPlot <- renderPlotly(p) observeEvent(input$descrXaxisResetBtn, { updateSelectInput("descrxaxis", selected = character(0)) }) })

    to

     observeEvent(input$descrBtnPlot,{... output$descrSummaryStatsPlot <- renderPlotly(p) }) observeEvent(input$descrXaxisResetBtn, { updateSelectInput("descrxaxis", selected = character(0)) })

    (though this is incomplete, see the next point).

  • Second, the first argument of any update* function is the session . This is not optional. The code in bullet 1 above should really be

     observeEvent(input$descrBtnPlot,{... output$descrSummaryStatsPlot <- renderPlotly(p) }) observeEvent(input$descrXaxisResetBtn, { updateSelectInput(session, "descrxaxis", selected = character(0)) # ^^^^^^^^ the only difference })

    This leads me to the last bullet:

  • Third, your server <- function(input, output) is fine when you don't use any update* functions, but in line with the second point above, you must have session , which means you need to change your server definition to

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

I'll use the example from ?updateSelectInput to demonstrate how to find the right answer, but injecting a single browser() before the actual call.

library(shiny)

ui <- fluidPage(
  p("The checkbox group controls the select input"),
  checkboxGroupInput("inCheckboxGroup", "Input checkbox",
    c("Item A", "Item B", "Item C")),
  selectInput("inSelect", "Select input",
    c("Item A", "Item B", "Item C"))
)

server <- function(input, output, session) {
  observe({
    x <- input$inCheckboxGroup

    # Can use character(0) to remove all choices
    if (is.null(x))
      x <- character(0)

    browser()

    # Can also set the label and select items
    updateSelectInput(session, "inSelect",
      label = paste("Select input label", length(x)),
      choices = x,
      selected = tail(x, 1)
    )
  })
}

shinyApp(ui, server)
  1. When you run this the first time, it'll start with an empty selector, so we can just c ontinue out of that debugger.

  2. Select an item. The call to updateSelectInput sets selected = tail(x, 1) , so if we run that on the console, we'll see

    Browse[2]> tail(x, 1) [1] "Item A"

    c ontinue out of this debugger, notice the selector now says Item A .

  3. Deselect the "A" checkbox, and you'll be in the debugger again.

     Browse[4]> tail(x, 1) character(0)

    c ontinue out of this debugger, and you'll see the selector is now empty (deselected).

Why? Internally, looking at the source for updateSelectInput (as of 1.4.0.2),

updateSelectInput
# function (session, inputId, label = NULL, choices = NULL, selected = NULL) 
# {
#     choices <- if (!is.null(choices)) 
#         choicesWithNames(choices)
#     if (!is.null(selected)) 
#         selected <- as.character(selected)
#     options <- if (!is.null(choices)) 
#         selectOptions(choices, selected)
#     message <- dropNulls(list(label = label, options = options, 
#         value = selected))
#     session$sendInputMessage(inputId, message)
# }
# <bytecode: 0x00000000b8f06030>
# <environment: namespace:shiny>

see that all it checks is .is.null(selected) , so your thought to use selected=NULL is both its default value and it is used as the choice to "do not change the selected value".


As a more specific example, I'll start with the (non-debugged) version of that app, and add a single "Reset!" button that will clear the selection in the selectInput :

ui <- fluidPage(
  p("The checkbox group controls the select input"),
  checkboxGroupInput("inCheckboxGroup", "Input checkbox",
    c("Item A", "Item B", "Item C")),
  selectInput("inSelect", "Select input",
    c("Item A", "Item B", "Item C")),
  actionButton("resetsel", "Reset!")
)

server <- function(input, output, session) {
  observe({
    x <- input$inCheckboxGroup

    # Can use character(0) to remove all choices
    if (is.null(x))
      x <- character(0)

    # Can also set the label and select items
    updateSelectInput(session, "inSelect",
      label = paste("Select input label", length(x)),
      choices = x,
      selected = tail(x, 1)
    )
  })

  observeEvent(input$resetsel, {
    ### either
    updateSelectInput(session, "inSelect", selected = character(0))
    ### or
    # updateSelectInput(session, "inSelect", selected = "")
    ### both do the same thing here
  })
}

shinyApp(ui, server)

Now, the basic operation of the shiny demo works, but when you click on the reset button, the selection is cleared. FYI, if you don't have changes for choices= , you don't need to include that in your call to updateSelectInput . It doesn't hurt, but it is only necessary if you believe the list of choices may need to be updated/changed otherwise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM