R Shiny multiple selectInputs - prevent reactivity from occurring due to updateSelectInput

34 Views Asked by At

Sorry in advance for the odd title, but here is what I'm trying to accomplish.

I have two selectInput boxes, one for each type of selection (in this contrived example in the code that follows the selections are different types of charts to display). The user needs to be able to select from either input dropdown the chart they would like displayed. If the updateSelectInput code is not present, the code works, but in that case if the user makes a selection in the Summary chart, say Sum2, then selects Sev3 from the other dropdown, and then wants to redisplay Sum2, they need to select some other option in the Summary chart first, then reselect Sum2 in order for the reactivity to take place. The inputSelect doesn't see a change when you click on the already displayed option.

With the updateSelectInput code present, the situation is worse (as I should have expected). When the user moves from Summary Chart to Severity chart and selects an option (say Sev3), both dropdowns reset to the space holder, select, because of the way reactivity works.

Is there anyway to prevent this from happening? I know I can put all the options in the same dropdown, but there are other reasons why this is not an option for me in the real-world code which this simple example does not show.

library(shiny)

summaryChartSelections <- c("<select>", "Sum1", "Sum2", "Sum3")
severityChartSelections <- c("<select>", "Sev1", "Sev2", "Sev3")

ui = fluidPage(tabPanel(
  "Charts",
  box(
    title = "Chart picker",
    width = 12,
    background = NULL,
    fluidRow(style = "padding-bottom: 20px;",
             column(
               3,
               selectInput(
                 "chartTypeA",
                 "Summary Chart:",
                 choices = summaryChartSelections
               )
             ),
             column(
               3,
               selectInput(
                 "chartTypeB",
                 "Severity Chart:",
                 choices = severityChartSelections
               )
             ))
  ),
  fluidRow(column(12,
                  textOutput("theSelection")))
))

server <- function(input, output, session) {
  dataChange <- reactiveValues(chartType = "")
  
  observeEvent(input$chartTypeA,
               {
                 dataChange$chartType <<- "Standard"
                 updateSelectInput(session, "chartTypeB", "Summary Chart:",
                                   choices <- severityChartSelections)
               })
  
  observeEvent(input$chartTypeB,
               {
                 dataChange$chartType <<- "Severity"
                 updateSelectInput(session, "chartTypeA", "Severity Chart:",
                                   choices <- summaryChartSelections)
               })
  
  reactiveChart <- reactive({
    if (dataChange$chartType == "Standard") {
      printText <- paste0("Chart A selection: ", input$chartTypeA)
    } else {
      printText <- paste0("Chart B selection: ", input$chartTypeB)
    }
  })
  
  output$theSelection = renderText({
    reactiveChart()
  })
  
}

# Run the application
shinyApp(ui = ui, server = server)

1

There are 1 best solutions below

0
Stéphane Laurent On
library(shiny)

summaryChartSelections <- c("select", "Sum1", "Sum2", "Sum3")
severityChartSelections <- c("select", "Sev1", "Sev2", "Sev3")

ui = fluidPage(
    fluidRow(style = "padding-bottom: 20px;",
             column(
               3,
               selectizeInput(
                 "chartTypeA",
                 "Summary Chart:",
                 choices = summaryChartSelections,
                 options = list(
                   onChange = I("function(value) {
                                Shiny.setInputValue('which', 'chartTypeA', {priority: 'event'});
                                Shiny.setInputValue('valueA', this.items[0], {priority: 'event'});
                                }")
                 )
               )
             ),
             column(
               3,
               selectizeInput(
                 "chartTypeB",
                 "Severity Chart:",
                 choices = severityChartSelections,
                 options = list(
                   onChange = I("function(value) { 
                                Shiny.setInputValue('which', 'chartTypeB', {priority: 'event'});
                                Shiny.setInputValue('valueB', this.items[0], {priority: 'event'});
                                }")
                 )
               )
             )
  ),
  fluidRow(column(12,
                  textOutput("theSelection")))
)

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

  observeEvent(input$which, {
    if(input$which == "chartTypeA") {
      updateSelectInput(session, "chartTypeB", "Summary Chart:",
                        choices = severityChartSelections)
    } else {
      updateSelectInput(session, "chartTypeA", "Severity Chart:",
                        choices = summaryChartSelections)
    }
  })
  
  reactiveChart <- reactive({
    if (!is.null(input$which) && input$which == "chartTypeA") {
      paste0("Chart A selection: ", input$valueA)
    } else {
      paste0("Chart B selection: ", input$valueB)
    }
  })

  output$theSelection = renderText({
    reactiveChart()
  })
  
}

# Run the application
shinyApp(ui = ui, server = server)