rshinyshiny-reactivity

How to stop reactive functions from repeating in Shiny?


I am trying to simplify the search feature in a Shiny app and notice the reactive functions keep repeating and overwriting what I would like to display.

There are two variables I want to allow a user to search for 1) County and 2) Zip Code. I would like to have the label above the search box change based on the radio button selected (County or Zip Code), and ideally reduce the list of available choices one can select.

So if you select Zip Code you are presented with a list of Zip Codes and if you select County you just see the list of counties. As you can see from the code below, its somewhat functional in terms of the output, but the dynamic label and the dynamic select lists don't always work.

library(shiny)
library(dplyr)    
library(tidyverse)
library(tibble)
library(DT)

county_list = c('Kings','Rockland','Orange','New York','Richmond','Kings','Rockland','Orange','New York','Richmond')
zip_list = c('11230','10901','12550','10023','10044','11230','10901','12550','10023','10044')
store_name = c('Store 1','Store 2', 'Store 3','Store 4', 'Store 5','Store 1','Store 7', 'Store 8','Store 9', 'Store 10')

db = tibble(Store = store_name ,County = county_list, ZipCode = zip_list)

ui <- fluidPage(  
  
  titlePanel("Title"),
  tabsetPanel(
    tabPanel('Data',  
             
             radioButtons("county_or_zip_select","Choose:",choices=c("County","ZipCode")),
             selectInput("search4_all", "search_box:", selectize = FALSE,choices=unique(c(county_list,zip_list))),
             DT::DTOutput('data')
             )
    ))

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

    getData <- reactive({
      if(input$county_or_zip_select=='County'){
        df<-db[grep(input$search4_all, db$County,ignore.case = T),]
        updateSelectInput(session,"search4_all",label='Select County:')
        
      }else{
        df<-db[grep(input$search4_all, db$ZipCode, ignore.case = T),]}
        updateSelectInput(session,"search4_all",label='Select Zip Code:')
      
      df  
    })

    output$data <- DT::renderDT(getData(),options = list(lengthMenu = c(5, 10), pageLength = 5)) # Refers to DT::DTOutput('data') in main panel section
       
} 
shinyApp(ui = ui, server = server)

Note: I posted a similar question the other day which I have since deleted (or tried to), but I did not incorporate updatSelectInput and more importantly, I did not provide an MWE as was pointed out. Sorry about that.


Solution

  • You could create two separate selectInput and use shinyjs to toggle one or the other depending on radio button value :

    library(shiny)
    library(shinyjs)
    library(dplyr)    
    library(tidyverse)
    library(tibble)
    library(DT)
    
    county_list = c('Kings','Rockland','Orange','New York','Richmond','Kings','Rockland','Orange','New York','Richmond')
    zip_list = c('11230','10901','12550','10023','10044','11230','10901','12550','10023','10044')
    store_name = c('Store 1','Store 2', 'Store 3','Store 4', 'Store 5','Store 1','Store 7', 'Store 8','Store 9', 'Store 10')
    
    db = tibble(Store = store_name ,County = county_list, ZipCode = zip_list)
    
    ui <- fluidPage(  
      
      titlePanel("Title"),
      shinyjs::useShinyjs(),
      tabsetPanel(
        tabPanel('Data',  
                 
                 radioButtons("county_or_zip_select","Choose:",choices=c("County","ZipCode")),
                 selectInput("selectCounty", "Select county", selectize = FALSE,choices=unique(county_list)),
                 selectInput("selectZipcode", "Select zip code", selectize = FALSE,choices=unique(zip_list)),
                 DT::DTOutput('data')
        )
      ))
    
    server <- function(input, output, session) {
      
      observe( {
        shinyjs::toggle('selectCounty',condition = input$county_or_zip_select=='County')
        shinyjs::toggle('selectZipcode',condition = input$county_or_zip_select=='ZipCode')
      })
    
      getData <- reactive({
        if(input$county_or_zip_select=='County'){
          db[grep(input$selectCounty, db$County,ignore.case = T),]
        } else {
          db[grep(input$selectZipcode, db$ZipCode, ignore.case = T),]}
      })
      
      output$data <- DT::renderDT(getData(),options = list(lengthMenu = c(5, 10), pageLength = 5)) # Refers to DT::DTOutput('data') in main panel section
      
    } 
    shinyApp(ui = ui, server = server)
    

    Note that a call to shinyjs::useShinyjs() is needed in the UI so that shinyjs works properly.