Search code examples
javascriptrshinydt

Build links between tabs with sidepanels/conditional panel


This is a question building on top of the discussion on links between tabs in shiny. This solution is just what I need, however my side panel does not change when the table is clicked on.

So my question is how can I make the side panel change too when clicking on the link in the table?

Here is some replicable code:

library(shiny)
library(DT)

server <- function(input, output) {
  output$iris_type <- DT::renderDataTable({
    datatable(data.frame(Species=paste0("<a href='#filtered_data'",
                                        "alt='",unique(iris$Species),"'",                                                 
                                        "onclick=\"",
                                        "tabs = $('.tabbable .nav.nav-tabs li');",
                                        "tabs.each(function() {",
                                        "$(this).removeClass('active')",
                                        "});",
                                        "$(tabs[1]).addClass('active');",
                                        "tabsContents = $('.tabbable .tab-content .tab-pane');",
                                        "tabsContents.each(function() {",
                                        "$(this).removeClass('active')",
                                        "});",
                                        "$(tabsContents[1]).addClass('active');",
                                        "$('#filtered_data').trigger('change').trigger('shown');",
                                        "Shiny.onInputChange('species', getAttribute('alt'));",
                                        "\">",
                                        unique(iris$Species),
                                        "</a>")),
                              escape = FALSE)
  })

  output$filtered_data <- DT::renderDataTable({
    if(is.null(input$species)){
      datatable(iris)
    }else{
      datatable(iris[iris$Species %in% input$species, ])
    }
  })
}

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      conditionalPanel(
        'input.dataset === "Iris Type"',
        helpText("This is the full Iris panel")
      ),
      conditionalPanel(
        'input.dataset === "Filtered Data"',
        helpText("This is the filtered panel")
      ),
      width = 2
    ),
  mainPanel(
    tabsetPanel(
      id = 'dataset',
      tabPanel("Iris Type", DT::dataTableOutput("iris_type")),
      tabPanel("Filtered Data", DT::dataTableOutput("filtered_data"))
    )
  ))
)

shinyApp(ui = ui, server = server)

Solution

  • If I understood your question correct, I guess you can just add "Shiny.onInputChange('dataset', 'Filtered Data');", to your javascript.

    Full code:

    
    
    library(shiny)
    library(DT)
    
    server <- function(input, output) {
      output$iris_type <- DT::renderDataTable({
        datatable(data.frame(Species=paste0("<a href='#filtered_data'",
                                            "alt='",unique(iris$Species),"'",                                                 
                                            "onclick=\"",
                                            "tabs = $('.tabbable .nav.nav-tabs li');",
                                            "tabs.each(function() {",
                                            "$(this).removeClass('active')",
                                            "});",
                                            "$(tabs[1]).addClass('active');",
                                            "tabsContents = $('.tabbable .tab-content .tab-pane');",
                                            "tabsContents.each(function() {",
                                            "$(this).removeClass('active')",
                                            "});",
                                            "$(tabsContents[1]).addClass('active');",
                                            "$('#filtered_data').trigger('change').trigger('shown');",
                                            "Shiny.onInputChange('species', getAttribute('alt'));",
                                            "Shiny.onInputChange('dataset', 'Filtered Data');",
                                            "\">",
                                            unique(iris$Species),
                                            "</a>")),
                  escape = FALSE)
      })
    
      output$filtered_data <- DT::renderDataTable({
        if(is.null(input$species)){
          datatable(iris)
        }else{
          datatable(iris[iris$Species %in% input$species, ])
        }
      })
    }
    
    ui <- fluidPage(
      sidebarLayout(
        sidebarPanel(
          conditionalPanel(
            'input.dataset === "Iris Type"',
            helpText("This is the full Iris panel")
          ),
          conditionalPanel(
            'input.dataset === "Filtered Data"',
            helpText("This is the filtered panel")
          ),
          width = 2
        ),
        mainPanel(
          tabsetPanel(
            id = 'dataset',
            tabPanel("Iris Type", DT::dataTableOutput("iris_type")),
            tabPanel("Filtered Data", DT::dataTableOutput("filtered_data"))
          )
        ))
    )
    
    shinyApp(ui = ui, server = server)