Shiny: How to prevent selectInput from being reset by selecting the second selectInput


Dave

This builds on a question I ran into here , but I'm simplifying the example to make it easier to read (and therefore easier for future searchers).

reproducible example

Here is the data:

library(tidyverse)
library(shiny)

food_table <- structure(list(Food_category = c("Fruit", "Fruit", "Fruit", "Fruit", 
                                               "Vegetable", "Vegetable", "Fruit", "Fruit", "Fruit", "Vegetable"
), Food = c("Granny Smith apple", "McIntosh apple", "Avocado", 
            "Blueberries", "Broccoli, steamed", "Cucumber", "Banana", "Cherries", 
            "Nectarine", "Red onion"), Serving_Size = c(1, 1, 0.333333333333333, 
                                                        1, 1, 1, 1, 1, 1, 1), Serving_Unit = c("apple", "apple", "avocado", 
                                                                                               "cup", "cup", "cup", "banana", "cup", "nectarine", "cup"), Carbs_per_Serving = c(25, 
                                                                                                                                                                                25, 4, 21, 3.5, 4, 27, 25, 15, 11)), row.names = c(NA, -10L), class = c("tbl_df", 
                                                                                                                                                                                                                                                        "tbl", "data.frame"))


(food_table)

   Food_category Food               Serving_Size Serving_Unit Carbs_per_Serving
   <chr>         <chr>                     <dbl> <chr>                    <dbl>
 1 Fruit         Granny Smith apple        1     apple                     25  
 2 Fruit         McIntosh apple            1     apple                     25  
 3 Fruit         Avocado                   0.333 avocado                    4  
 4 Fruit         Blueberries               1     cup                       21  
 5 Vegetable     Broccoli, steamed         1     cup                        3.5
 6 Vegetable     Cucumber                  1     cup                        4  
 7 Fruit         Banana                    1     banana                    27  
 8 Fruit         Cherries                  1     cup                       25  
 9 Fruit         Nectarine                 1     nectarine                 15  
10 Vegetable     Red onion                 1     cup                       11  

I have a shiny app which has multiple inputs. This works, except when a new selection is made in the second food category box, the food selection in the first row changes back to the first element. In other words, if I select "Fruit" in the first row, then "Avocado" and "1", then when I go to the second row and select "Vegetables", the selected food item changes from "Avocado" " becomes "Grandma "Smith Apple". I'm trying to figure out how to prevent the row from resetting after making a selection.

Here is the stripped down shiny code:

# Table filters
categories <- sort(unique(food_table$Food_category))
foods      <- sort(unique(food_table$Food))
unit       <- sort(unique(food_table$Serving_Unit))

# Create Shiny app 

   # Define UI
    ui <- fluidPage(headerPanel(strong("Carbohydrate Calculator")),
                    
                    fluidRow(
                      column(
                        width = 3,
                        selectInput(
                          inputId = 'cat_1',
                          label   = 'Food Category',
                          choices = c("None", categories)
                        )),
                      column(
                        width = 3,
                        selectInput(
                          inputId = 'food_1',
                          label   = 'Food Item',
                          choices = foods
                        )),
                      column(
                        width = 3,
                        numericInput(
                          inputId = "actual_serving_1",
                          label = "How much?",
                          value = "",
                          min = 0,
                          max = 100
                        ))
                    ),
                    fluidRow(
                      column(
                        width = 3,
                        selectInput(
                          inputId = 'cat_2',
                          label   = 'Food Category',
                          choices = c("None", categories)
                        )),
                      column(
                        width = 3,
                        selectInput(
                          inputId = 'food_2',
                          label   = 'Food Item',
                          choices = foods
                        )),
                      column(
                        width = 3,
                        numericInput(
                          inputId = "actual_serving_2",
                          label = "How much?",
                          value = "",
                          min = 0,
                          max = 100
                        ))
                    ),
                    
                    column(8,
                           tableOutput("my_table"),
                           span(textOutput("my_message"), style="color:red")
                    ) # Column close
                    
    )                 # fluidPage close
    
    
    
    # Define server logic required to draw a histogram
    server <- function(input, output, session) {
      
      
      food_table_1 <- reactive({
        food_table %>%
          filter(Food_category == input$cat_1) %>% 
          filter(Food == input$food_1) %>% 
          mutate(Actual_amount = input$actual_serving_1) 
      })
      
      food_table_2 <- reactive({
        food_table %>%
          filter(Food_category == input$cat_2) %>% 
          filter(Food == input$food_2) %>% 
          mutate(Actual_amount = input$actual_serving_2) 
      })
      
    
      
      # Combine selections into a single table
      combined_tables <- reactive({
        do.call("rbind", list(food_table_1(),
                              food_table_2()
        )
        ) %>% 
          mutate(Total_Carbs_grams = Carbs_per_Serving * Actual_amount / Serving_Size) %>% 
          select(Food_category, Food, Serving_Size, Serving_Unit, Actual_amount, Carbs_per_Serving, Total_Carbs_grams, everything())
      })
      
      
      # Render Output table
      output$my_table <- renderTable({
        
        combined_tables()
        
      })
      
      
      
      # Create observe function which updates the second selectInput when the first selectInput is changed
      observe({
        
        updateSelectInput(
          session,
          inputId = "food_1",
          choices = food_table %>% filter(Food_category == input$cat_1) %>% pull(Food)
        )
        
        updateSelectInput(
          session,
          inputId = "food_2",
          choices = food_table %>% filter(Food_category == input$cat_2) %>% pull(Food)
        )
        
        
      }) # Observe close
    }    # Server close
    
    
    
    # Run the application 
    shinyApp(ui = ui, server = server)
ronak shah

You can set selectedin updateSelectInputand input$food_1respectively input$food_2.

updateSelectInput(
      session,
      inputId = "food_1",
      choices = food_table %>% filter(Food_category == input$cat_1) %>% pull(Food), 
      selected = input$food_1
    )

Complete application code -

library(shiny)
library(dplyr)

categories <- sort(unique(food_table$Food_category))
foods      <- sort(unique(food_table$Food))
unit       <- sort(unique(food_table$Serving_Unit))

# Create Shiny app 

# Define UI
ui <- fluidPage(headerPanel(strong("Carbohydrate Calculator")),
                
                fluidRow(
                  column(
                    width = 3,
                    selectInput(
                      inputId = 'cat_1',
                      label   = 'Food Category',
                      choices = c("None", categories)
                    )),
                  column(
                    width = 3,
                    selectInput(
                      inputId = 'food_1',
                      label   = 'Food Item',
                      choices = foods
                    )),
                  column(
                    width = 3,
                    numericInput(
                      inputId = "actual_serving_1",
                      label = "How much?",
                      value = "",
                      min = 0,
                      max = 100
                    ))
                ),
                fluidRow(
                  column(
                    width = 3,
                    selectInput(
                      inputId = 'cat_2',
                      label   = 'Food Category',
                      choices = c("None", categories)
                    )),
                  column(
                    width = 3,
                    selectInput(
                      inputId = 'food_2',
                      label   = 'Food Item',
                      choices = foods
                    )),
                  column(
                    width = 3,
                    numericInput(
                      inputId = "actual_serving_2",
                      label = "How much?",
                      value = "",
                      min = 0,
                      max = 100
                    ))
                ),
                
                column(8,
                       tableOutput("my_table"),
                       span(textOutput("my_message"), style="color:red")
                ) # Column close
                
)                 # fluidPage close



# Define server logic required to draw a histogram
server <- function(input, output, session) {
  
  
  food_table_1 <- reactive({
    food_table %>%
      filter(Food_category == input$cat_1) %>% 
      filter(Food == input$food_1) %>% 
      mutate(Actual_amount = input$actual_serving_1) 
  })
  
  food_table_2 <- reactive({
    food_table %>%
      filter(Food_category == input$cat_2) %>% 
      filter(Food == input$food_2) %>% 
      mutate(Actual_amount = input$actual_serving_2) 
  })
  
  
  
  # Combine selections into a single table
  combined_tables <- reactive({
    do.call("rbind", list(food_table_1(),
                          food_table_2()
    )
    ) %>% 
      mutate(Total_Carbs_grams = Carbs_per_Serving * Actual_amount / Serving_Size) %>% 
      select(Food_category, Food, Serving_Size, Serving_Unit, Actual_amount, Carbs_per_Serving, Total_Carbs_grams, everything())
  })
  
  
  # Render Output table
  output$my_table <- renderTable({
    
    combined_tables()
    
  })
  
  
  
  # Create observe function which updates the second selectInput when the first selectInput is changed
  observe({
    
    updateSelectInput(
      session,
      inputId = "food_1",
      choices = food_table %>% filter(Food_category == input$cat_1) %>% pull(Food), 
      selected = input$food_1
    )
    
    updateSelectInput(
      session,
      inputId = "food_2",
      choices = food_table %>% filter(Food_category == input$cat_2) %>% pull(Food), 
      selected = input$food_2
    )
    
    
  }) # Observe close
}    # Server close



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

Related


Reset selectInput to NULL in R Shiny

User 8229029 I need to be able to reset several selectInput widgets in R Shiny to their original value NULL (with a blank text area in the widget). So far I'm getting user input (which variable to use as the x-axis) like this: output$descrxaxis_Variable <- r

Reset selectInput to NULL in R Shiny

User 8229029 I need to be able to reset several selectInput widgets in R Shiny to their original value NULL (with a blank text area in the widget). So far I'm getting user input (which variable to use as the x-axis) like this: output$descrxaxis_Variable <- r

Reset selectInput to NULL in R Shiny

User 8229029 I need to be able to reset several selectInput widgets in R Shiny to their original value NULL (with a blank text area in the widget). So far I'm getting user input (which variable to use as the x-axis) like this: output$descrxaxis_Variable <- r

Reset selectInput to NULL in R Shiny

User 8229029 I need to be able to reset several selectInput widgets in R Shiny to their original value NULL (with a blank text area in the widget). So far I'm getting user input (which variable to use as the x-axis) like this: output$descrxaxis_Variable <- r

Prevent selectInput from wrapping

Adam_G In a shiny app, is there a way to prevent text selectInput()wrapping in a dropdown menu as shown in the screenshot below? Each option is a long text string. I want that dropdown to display each long string on one line without creating a huge sidebar. Sy

shiny update data from selectInput

username I'm having trouble getting the output of selectizeInput to update the uploaded csv data. The specific block of code in question is observeEvent(input$Go, { tmp <- values$df_data output$Grp = renderUI({ lvls <- tmp %>% pull(Group

shiny update data from selectInput

username I'm having trouble getting the output of selectizeInput to update the uploaded csv data. The specific block of code in question is observeEvent(input$Go, { tmp <- values$df_data output$Grp = renderUI({ lvls <- tmp %>% pull(Group

Assign variable from selectInput in Shiny - R

User 5015341 I want to do an exercise in Shiny where I select some variables from a menu. The options in the menu have the same names as the variables in the dataset. Then I want to make some predictions between the variables that have been selected. My datase

Filter data from API using selectInput in Shiny

turn signal Because many days I can't solve my problem. At the beginning, I get some data from the API (I refresh the API call every 5 seconds to get the latest data). The data contains information about locations (latitude and longitude), and some labels writ

Shiny R watchEvent with multiple conditions from selectInput

Then I'm working on a shiny app and I'm having functional difficulties observeEvent()creating complex expressions with multiple inputs all derived from selectInput(). My problem is that some observeEvent()functions inside expressions fire on startup, causing t

Filter data from API using selectInput in Shiny

turn signal Because many days I can't solve my problem. At the beginning, I get some data from the API (I refresh the API call every 5 seconds to get the latest data). The data contains information about locations (latitude and longitude), and some labels writ

Shiny R watchEvent with multiple conditions from selectInput

Then I'm working on a shiny app and I'm having functional difficulties observeEvent()creating complex expressions with multiple inputs all derived from selectInput(). My problem is that some observeEvent()functions inside expressions fire on startup, causing t

Shiny R watchEvent with multiple conditions from selectInput

Then I'm working on a shiny app and I'm having functional difficulties observeEvent()creating complex expressions with multiple inputs all derived from selectInput(). My problem is that some observeEvent()functions inside expressions fire on startup, causing t

Handling Java: Prevent selectInput from opening indefinitely

Henry Zhu When I create an "Open File" button using selectInput(). The problem is that the program keeps opening windows every time the user selects a file. How to prevent this from happening? void setup() { size(500, 500); background(255); } void draw()

Handling Java: Prevent selectInput from opening indefinitely

Henry Zhu When I create an "Open File" button using selectInput(). The problem is that the program keeps opening windows every time the user selects a file. How to prevent this from happening? void setup() { size(500, 500); background(255); } void draw()

Handling Java: Prevent selectInput from opening indefinitely

Henry Zhu When I create an "Open File" button using selectInput(). The problem is that the program keeps opening windows every time the user selects a file. How to prevent this from happening? void setup() { size(500, 500); background(255); } void draw()

R Shiny - how to display select label in selectInput

Belief I have defined a selectInput as follows. I would like to access each option's label and render it on the main panel. If the user selects "Sugar sugar bev.", I want to render something like this on the main panel: "You selected Sugar sweetened bev." but

How to color selectInput placeholder hint in Shiny?

Slope Mountain I'm trying to make a blue "select" prompt in a SelectInputbox (Segment mIgration) to look similar to other input boxes but failed. Here's a piece of code I'm using in the UI part: column(width=2, selectInput(inputId = "SEG_MIG",

R Shiny - how to display select label in selectInput

Belief I have defined a selectInput as follows. I would like to access each option's label and render it on the main panel. If the user selects "Sugar sugar bev.", I want to render something like this on the main panel: "You selected Sugar sweetened bev." but