Jensxy
Jensxy

Reputation: 139

Shiny DT - Select row after selected row by using a button

So far, I select a row of a datatable containing the name of documents and get information from a database regarding the selected document. The overview of this information is in another tab. Now, I like to have a button "Next" to select the row after the selected, to show the information of the next document. I cannot use the rownumber+1 because my datatable is ordered. Is there a way to get the row after my selected row by using a button?

UPDATE:

library(DT)
# ui
ui <- tagList(
  ui <- basicPage(
    h2("My Table"),
    DT::dataTableOutput("DT_show_docs"),
    textOutput("printScore"),
    actionButton("next_doc", "Next Document")
  )
)

# Server
server <- function(input, output, session) {
  doc_overview <- reactive({
    df <- data.frame(Doc_ID = seq(1,100), Filename = paste0("File_",seq(1,100)), Score = sample(1:10,100,replace=TRUE), Approved = rep(c("No", "Yes"), times = c(95,5)), Date = rep(seq(as.Date("2018/01/01"), as.Date("2018/1/10"), "days"), length.out=100))
    return(df)
  })

  output$DT_show_docs <- renderDataTable({

    DT::datatable(doc_overview(), 
                  options = list(
                    searching       = FALSE,
                    order           = list(list(3, 'desc'))),
                  selection = "single")

  })

  output$printScore <- renderText({
    row <- input$DT_show_docs_rows_selected
    text <- doc_overview()[row, "Filename"]
  })

  observeEvent(input$next_doc, {
   # Function to select next row/document from datatable. When the button is clicked,
   # and the first row is selected at this moment, I want to select/print the second 
   # row and so on.
  })
}

# app
shinyApp(ui = ui, server = server)

Upvotes: 2

Views: 1736

Answers (1)

Shree
Shree

Reputation: 11140

I have a feeling (could be wrong) that this might be a case of XY Problem trap i.e. you are asking for help with your attempt at solving a problem rather than with the underlying problem itself. If this is the case, you are better off asking another question explaining your core requirement which might yield a simpler overall solution. Although my solution is pretty straightforward the whole thing just feels like an unnecessary complication.

Anyways, here's one way to do this. You can get the current order of rows on the datatable using input$tableId_rows_all which gives the indices of rows on all pages (after the table is filtered by the search strings). output$test shows this order in real-time. Now you just need to cycle through this order every time user hits next_doc action button.

This solution will work even if you reorder your rows or manually change selected row.

library(shiny)
library(DT)

ui <- tagList(
  ui <- basicPage(
    h2("My Table"),
    DT::dataTableOutput("DT_show_docs"),
    textOutput("printScore"),
    actionButton("next_doc", "Next Document"),
    verbatimTextOutput("test")
  )
)

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

  doc_overview <- reactive({
    df <- data.frame(Doc_ID = seq(1,12), 
                     Filename = paste0("File_",seq(1,12)), 
                     Score = sample(1:10,12,replace=TRUE), 
                     Approved = rep(c("No", "Yes"), times = c(5,7)), 
                     Date = rep(seq(as.Date("2018/01/01"), as.Date("2018/1/10"), "days"), length.out=12))
    return(df)
  })

  output$DT_show_docs <- renderDataTable({

    DT::datatable(doc_overview(), 
                  options = list(
                    searching       = FALSE,
                    order           = list(list(3, 'desc'))),
                  selection = "single")

  })

  row_index <- reactiveValues(index = 1)

  observe({ # reset row_index when you manually select any row
    row_index$index <- which(input$DT_show_docs_rows_selected == input$DT_show_docs_rows_all)
  })

  DT_show_docs_proxy <- dataTableProxy("DT_show_docs")

  output$printScore <- renderText({
    row <- input$DT_show_docs_rows_selected
    text <- doc_overview()[row, "Filename"]
  })

  observeEvent(input$next_doc, {
   # Function to select next row/document from datatable. When the button is clicked,
   # and the first row is selected at this moment, I want to select/print the second 
   # row and so on.
    req(input$DT_show_docs_rows_selected) # must select some row before using next_doc button
    row_order <- input$DT_show_docs_rows_all # gives current order of rows
    row_index$index <- isolate(row_index$index) + 1 # cycles throw the order one by one when you click next_button
    selectRows(DT_show_docs_proxy, selected = row_order[row_index$index]) # selects the row of current index
  })

  output$test <- renderPrint({
    input$DT_show_docs_rows_all # shows the order of rows in real time
  })
}

# app
shinyApp(ui = ui, server = server)

Upvotes: 3

Related Questions