Search code examples
shinyshinydashboardshiny-servershinyappsshinyjs

Persistent states of selectizeInput across different tabs in Shiny


I have the following Shiny app in which I have parent and child tabs. Clicking at the child tabs creates a selectizeInput with different default values. As you can see in the code, the ID for all child selectizeInput is same, and still, this control stores different states for each child selectizeInput.

I want to create a single selectizeInput for all child tabs and the value of this selectizeInput should be persistent/ same across all the tabs.

Please let me know what I am doing incorrectly.

enter image description here

library(shiny)
library(shinydashboard)

sidebar <- dashboardSidebar(
  collapsed = FALSE,
  sidebarMenu(id = "menu_sidebar",
              conditionalPanel(
                # https://community.rstudio.com/t/shiny-with-tabsetpanels-and-conditionpanel-not-hiding-what-it-should/57159/3
                condition = "input.main_tab == 'mother tab' && input.group_tab == 't_child1'",
                selectizeInput(inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = "APPLE")
              ),
              conditionalPanel(
                condition = "input.main_tab == 'mother tab' && input.group_tab == 't_child2'",
                selectizeInput(inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = "ORANGE")
              ),
              conditionalPanel(
                condition = "input.main_tab == 'mother tab' && input.group_tab == 't_child3'",
                selectizeInput(inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = "PEAR")
              ),
              conditionalPanel(
                condition = "input.main_tab == 'tab 1'",
                selectizeInput(inputId = "t1", label = "Select by:", choices = c(as.character(30:40)))
              ),
              conditionalPanel(
                condition = "input.main_tab == 'tab 2'",
                selectizeInput(inputId = "t2", label = "Select by:", choices = c(as.character(40:50)))
              )
  )
)


body <- dashboardBody(
  fluidRow(
    tabsetPanel(id = "main_tab",
                selected = "mother tab",
                tabPanel(title = "tab 1", "Tab content 1"),
                tabPanel(title = "tab 2", "Tab content 2"),
                tabPanel(title = "mother tab",
                         tabsetPanel(type = "tabs", id = "group_tab", selected = "Tab_child_2",
                                     tabPanel(title = "child_1", value = "t_child1", "Tab child content 1"),
                                     tabPanel(title = "child_2", value = "t_child2", "Tab child content 2"),
                                     tabPanel(title = "child_3", value = "t_child3", "Tab child content 3")
                         )
                )
                
    )
  )
)

shinyApp(
  ui = dashboardPage(
    dashboardHeader(title = "tabBoxes"),
    sidebar,
    body
  ),
  server = function(input, output) {
  }
)

Solution

  • I'd transfer the logic to the server side, as the UI part is rendered only once on startup:

    library(shiny)
    library(shinydashboard)
    
    sidebar <- dashboardSidebar(
      collapsed = FALSE,
      sidebarMenu(id = "menu_sidebar",
                  selectizeInput(inputId = "tc", label = "Select by:", choices = NULL)
      )
    )
    
    body <- dashboardBody(
      fluidRow(
        tabsetPanel(id = "main_tab",
                    selected = "mother tab",
                    tabPanel(title = "tab 1", "Tab content 1"),
                    tabPanel(title = "tab 2", "Tab content 2"),
                    tabPanel(title = "mother tab",
                             tabsetPanel(type = "tabs", id = "group_tab", selected = "Tab_child_2",
                                         tabPanel(title = "child_1", value = "t_child1", "Tab child content 1"),
                                         tabPanel(title = "child_2", value = "t_child2", "Tab child content 2"),
                                         tabPanel(title = "child_3", value = "t_child3", "Tab child content 3")
                             )
                    )
        )
      )
    )
    
    shinyApp(
      ui = dashboardPage(
        dashboardHeader(title = "tabBoxes"),
        sidebar,
        body
      ),
      server = function(input, output, session) {
        observeEvent(c(req(input$main_tab), input$group_tab), {
          
          if (input$main_tab == 'tab 1'){
            updateSelectizeInput(session, inputId = "tc", label = "Select by:", choices = c(as.character(30:40)), selected = isolate(input$tc))
          } else if (input$main_tab == 'tab 2'){
            updateSelectizeInput(session, inputId = "tc", label = "Select by:", choices = c(as.character(40:50)), selected = isolate(input$tc))
          }
          
          req(input$group_tab)
          if(input$main_tab == 'mother tab' && input$group_tab == 't_child1'){
            updateSelectizeInput(session, inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = isolate(input$tc))
          } else if (input$main_tab == 'mother tab' && input$group_tab == 't_child2'){
            updateSelectizeInput(session, inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = isolate(input$tc))
          } else if (input$main_tab == 'mother tab' && input$group_tab == 't_child3'){
            updateSelectizeInput(session, inputId = "tc", label = "Select by:", choices = c("APPLE", "ORANGE", "PEAR"), selected = isolate(input$tc))
          }
          
        })
      }
    )