0
votes

I'm building an app with multiple tabs. I want to let the user select a choice in one tab, then allowing them to sub-select from a downstream choice in the same tab. As the next step, I want the sub-selected choices to appear as the input choices in the second tab, allowing the user to sub-select again (independently of the first tab).

In the example below, selection of y leads to an update in the selection of z in the first tab. I want the user to be able to sub-select some z values (which are then plotted). I want the sub-selection of z values to then appear as the only choices in the second tab, and let the user sub-select further in the second tab.

What I have so far is in the code below. My issues are:

  1. the sub-selection of z in the first tab is obviously not working - the updateCheckboxGroupInput either un-selects everything (if I don't specify select = in the function, or it won't let me turn off some z values if I do specify select = choices.
  2. The updating and sub-selection in the second tab seem to work exactly as I want, and I don't understand why that behaviour is different between tabs.

Any help would be appreciated...

library(shiny)
library(dplyr)
library(ggplot2)

df <- data.frame(x = 1:10, y = letters[1:2], z = letters[1:10])
                                                
ui <- navbarPage("App", id = "nav", 
        tabPanel("Tab1", 
            selectInput("SelectY", label = "select value of y", choices = letters[1:2]),
            checkboxGroupInput("SelectZ", label = "select value of z", choices = "a", selected = "a"),
            plotOutput("plot1")),
        tabPanel("Tab2", 
            checkboxGroupInput("SelectZ2", label = "select a subset of z values selected in tab1", 
                choices = "a", selected = "a"),
            plotOutput("plot2")))
        
server = function(input, output, session){
    # function to update the SelectZ (in tab1) based on selection of "y", 
    # and update the SelectZ (in tab2) based on selection of "z" in tab1
    observe({
        y <- input$SelectY
        choices <- df[df$y %in% y,]$z
        updateCheckboxGroupInput(session, "SelectZ", choices = choices, select = choices)
        choices1 <- input$SelectZ
        updateCheckboxGroupInput(session, "SelectZ2", choices = choices1, select = choices1)
        }) 

    output$plot1 <- renderPlot({
        df %>% 
        filter(y == input$SelectY, z %in% input$SelectZ) %>%
        ggplot() +
        geom_point(aes(x = x, y = z))
                                })
                                
    output$plot2 <- renderPlot({
        df %>% 
        filter(y == input$SelectY, z %in% input$SelectZ2) %>%
        ggplot() +
        geom_point(aes(x = x, y = z))
                                })}

shinyApp(ui = ui, server = server)
1

1 Answers

0
votes

By splitting the observe part into two observeEvents the choices-object won't overwrite your unchecked boxes.

library(shiny)
library(dplyr)
library(ggplot2)

df <- data.frame(x = 1:10, y = letters[1:2], z = letters[1:10])

ui <- navbarPage("App", id = "nav", 
                 tabPanel("Tab1", 
                          selectInput("SelectY", label = "select value of y", choices = letters[1:2]),
                          checkboxGroupInput("SelectZ", label = "select value of z", choices = "a", selected = "a"),
                          plotOutput("plot1")),
                 tabPanel("Tab2", 
                          checkboxGroupInput("SelectZ2", label = "select a subset of z values selected in tab1", 
                                             choices = "a", selected = "a"),
                          plotOutput("plot2")))

server = function(input, output, session){
  # function to update the SelectZ (in tab1) based on selection of "y", 
  # and update the SelectZ (in tab2) based on selection of "z" in tab1
  observeEvent(input$SelectY, {
    choices <- df[df$y %in% input$SelectY,]$z
    updateCheckboxGroupInput(session, "SelectZ", choices = choices, select = choices)
  }) 
  
  observeEvent(input$SelectZ, {
    choices1 <- input$SelectZ
    updateCheckboxGroupInput(session, "SelectZ2", choices = choices1, select = choices1)
  })
  
  output$plot1 <- renderPlot({
    df %>% 
      filter(y == input$SelectY, z %in% input$SelectZ) %>%
      ggplot() +
      geom_point(aes(x = x, y = z))
  })
  
  output$plot2 <- renderPlot({
    df %>% 
      filter(y == input$SelectY, z %in% input$SelectZ2) %>%
      ggplot() +
      geom_point(aes(x = x, y = z))
  })}

shinyApp(ui = ui, server = server)