theneil
theneil

Reputation: 518

Shiny: updateSelectInput() selected argument issue with observe()

I'm using observe() to change a value of a selectInput after a user selects TRUE/FALSE in the Categorical drop down list. In the first tab of my program if you set Categorical to TRUE then Impute gets updated to mode and mean otherwise. I'm then able to change the Impute value as desired without it reverting to the value that appears when TRUE/FALSE is selected.

In the second tab I have a multiple selectInput list with a similar interface as the first tab; the interface is created for every value selected in Select covariates. In this section I also used observe() to update each selected covariates' Impute drop down list accordingly to the logic of the first tab (i.e. if TRUE is selected then Impute gets updated to mode and mean otherwise). However, the value in Impute appers to be locked in the sense that I'm not able to switch between values as I did in the first tab.

I don't know how to correct this issue and I was wondering if anyone out there has encountered this similar problem and has been able to fix it. Any advice or help would be greatly appreciated.

The code to my app can be seen below and can be ran in a single file.

library(shiny)
library(shinyjs)

ui <- shinyUI(fluidPage(
  shinyjs::useShinyjs(),
  navbarPage("Test",id="navbarPage",
             tabPanel("First tab", id = "first_tab",
                      sidebarLayout(
                        sidebarPanel(
                          selectInput('covariate.L.categorical', 'Categorical', c("",TRUE,FALSE)),
                          selectInput('covariate.L.impute', "Impute", c("","default","mean","mode","median"))
                        ),
                        mainPanel()
                      )
             ),
             tabPanel("Second tab", id = "second_tab",
                      sidebarLayout(
                        sidebarPanel(
                          selectInput('covariates', 'Select covariates', choices = c("age","sex","race","bmi"), multiple=TRUE, selectize=TRUE), 
                          tags$hr(),
                          uiOutput("covariateop")
                        ),
                        mainPanel()
                      )
             ))
))

server <- shinyServer(function(input, output, session) {
  
  rv <- reactiveValues(cov.selected = NULL)
  
  observe({
    updateSelectInput(session, "covariate.L.impute", selected = ifelse(input$covariate.L.categorical,"mode","mean"))
  })
  
  output$covariateop <- renderUI({  
    lapply(input$covariates, function(x){
      
      tags$div(id = paste0("extra_criteria_for_", x),
               h4(x),
               selectInput(paste0(x,"_categorical"), "Categorical",
                           choices = c("",TRUE,FALSE)),
               selectInput(paste0(x,"_impute"), "Impute",
                           choices = c("","default","mean","mode","median")),
               textInput(paste0(x,"_impute_default_level"), "Impute default level"),
               tags$hr()
      )
    })
  })
  observe({
    lapply(input$covariates, function(x){
      updateSelectInput(session, paste0(x,"_impute"), selected = ifelse(as.logical(reactiveValuesToList(input)[[paste0(x,"_categorical")]])==TRUE,"mode","mean"))
    })
  })
})

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

Upvotes: 0

Views: 267

Answers (1)

starja
starja

Reputation: 10365

In your observe in the second tab, you use reactiveValuesToList(input)[[paste0(x,"_categorical")]]. This means that this observe is reactive to any changes in any input element, so also if you change the "Imputation" input. You can just use input[[paste0(x,"_categorical")]] instead to get rid of this behaviour.

Note that the implementation of dynamic UI with lapply leads to the deletion and anew rendering of already existing input selections when an additional variable is selected. Maybe you can have a look at insertUI/removeUI to get a bit nicer UI.

Upvotes: 3

Related Questions