7

[Code]

library(shiny)

server <- function(input, output) {
  output$iris_type <- renderDataTable({
    data.frame(Species=paste0("<a href='#filtered_data'>", unique(iris$Species), "</a>"))
  })
  output$filtered_data <- renderDataTable({iris})
}

ui <- shinyUI(fluidPage(
  mainPanel(
    tabsetPanel(
      tabPanel("Iris Type", dataTableOutput("iris_type")),
      tabPanel("Filtered Data", dataTableOutput("filtered_data"))
    )
  )
))

shinyApp(ui = ui, server = server)

[Question]

I am trying to link the DataTable output on first tab to the second tab. For example, when I click on setosa, the next thing showing up is second tab with iris dataset containing only setosa. It should execute this piece of code from R: iris[iris$Species=="setosa",]. It should work for other Species in iris too.

How can I build up the link and run that R command by clicking?


[Update on answer]

In case you have a different layout and needs to be specific, here is what you can do.

  1. Your DataTable callback function:

    callback =
    "function(table) {
       table.on('click.dt', 'tr', function() {
         Shiny.onInputChange('rows', table.row(this).data()[0] );
         $(\".tabbable .nav.nav-tabs li a:contains('Filtered Data')\").click();
       });
     }"
    
  2. Your R code:

    output$filtered_data <- renderDataTable({
      tagString <- input$rows
      rawTags <- gsub("</a>", "", gsub("<a href='#filtered_data'>", "", tagString))
    
      if (identical(tagString, character(0))) {
        iris
      } else {
        ...
      }
    })
    
Boxuan
  • 4,937
  • 6
  • 37
  • 73

1 Answers1

4

It is easier to have the click function on the row of the first table. You can add a callback that looks for a click on the rows of the table. When a click is observed the row index is sent to a shiny reactive input:

library(shiny)

server <- function(input, output) {
  output$iris_type <- renderDataTable({
    data.frame(Species=paste0("<a href='#filtered_data'>", unique(iris$Species), "</a>"))
  },
  callback = "function(table) {
    table.on('click.dt', 'tr', function() {
      Shiny.onInputChange('rows', table.row( this ).index());
      tabs = $('.tabbable .nav.nav-tabs li a');
      $(tabs[1]).click();
    });
}")
  output$filtered_data <- renderDataTable({
    if(is.null(input$rows)){
      iris
    }else{
      iris[iris$Species %in% unique(iris$Species)[as.integer(input$rows)+1], ]
    }
  })
}

ui <- shinyUI(fluidPage(
  mainPanel(
    tabsetPanel(
      tabPanel("Iris Type", dataTableOutput("iris_type")),
      tabPanel("Filtered Data", dataTableOutput("filtered_data"))
    )
  )
))

shinyApp(ui = ui, server = server)
jdharrison
  • 30,085
  • 4
  • 77
  • 89
  • I've been looking online for a similar solution and this works well, but what I notice is that if you were to re-sort the links in the Iris Type table so that Virginica is on top and then click on the link for Virginica, it brings back Setosa columns in the Filtered Data tab. I think this is because the in the javascript "table.row" is pre-defined so that the first row is always Setosa, second Versicolor and third Virginica. Is there a way that the javascript could identify the name within the row, instead of the row number itself? – Andrew Ferris Aug 31 '15 at 04:39