firmo23
firmo23

Reputation: 8404

Inconsistent behavior during cell selection in DT datatable

I have the shiny app below in which the user clicks on a cell in the upper table and the relative cell should be displayed in the lower table. The issue is that when I unselect the cells in the upper the cells in the lower not only remain but become more.

library(shiny)
library(DT)
data("mtcars")

ui <- shinyUI(
  fluidRow(
    DT::dataTableOutput("myDatatable"),
    DT::dataTableOutput("myDatatable2")

  )

)

server <- shinyServer(function(input, output, session) {


  dat1 <- reactive({
    matrix(iris[,5])
  })


  list_all <- reactiveVal(character())
  observeEvent(input$myDatatable_cell_clicked, {
    list_all(append(list_all(), input$myDatatable_cell_clicked$value))
  })



  output$myDatatable <- DT::renderDataTable(dat1(), 
                                            selection=list( target="cell"),
                                            server = FALSE,
                                            rownames=FALSE)
  output$myDatatable2 <- DT::renderDataTable(matrix(list_all()), 
                                             selection="none",
                                             server = FALSE,
                                             rownames=FALSE)

})

shinyApp(ui, server)

Upvotes: 1

Views: 151

Answers (2)

ismirsehregal
ismirsehregal

Reputation: 33397

Here is another version based on input$myDatatable_cells_selected using reactive over reactiveVal (should always be the preferred way in shiny) + this works for multiple columns.

library(shiny)
library(DT)
library(datasets)

ui <- shinyUI(fluidRow(
  DT::dataTableOutput("myDatatable"),
  DT::dataTableOutput("myDatatable2")
))

server <- shinyServer(function(input, output, session) {
  dat1 <- reactive({
    data.frame(iris[, 5])
  })

  selected <- reactive({
    req(input$myDatatable_cells_selected)
    selected <- input$myDatatable_cells_selected
    selected[, 2] <- selected[, 2] + 1
    return(selected)
  })

  output$myDatatable <- DT::renderDataTable(
    dat1(),
    selection = list(target = "cell"),
    server = FALSE,
    rownames = FALSE
  )

  output$myDatatable2 <- DT::renderDataTable(
    data.frame(dat1()[selected()]),
    selection = "none",
    server = FALSE,
    rownames = FALSE)
})

shinyApp(ui, server)

Upvotes: 1

Eli Berkow
Eli Berkow

Reputation: 2725

Please try below:

library(shiny)
library(DT)
data("mtcars")

ui <- shinyUI(
    fluidRow(
        DT::dataTableOutput("myDatatable"),
        DT::dataTableOutput("myDatatable2")

    )

)

server <- shinyServer(function(input, output, session) {


    dat1 <- reactive({
        matrix(iris[,5])
    })


    list_all <- reactiveVal(character())
    observeEvent(input$myDatatable_cells_selected, {
        if (nrow(input$myDatatable_cells_selected) == 0) {
            list_all(character())
        } else {
            list_all(dat1()[input$myDatatable_cells_selected[,1]])
        }
    })



    output$myDatatable <- DT::renderDataTable(dat1(), 
                                              selection=list( target="cell"),
                                              server = FALSE,
                                              rownames=FALSE)
    output$myDatatable2 <- DT::renderDataTable(matrix(list_all()), 
                                               selection="none",
                                               server = FALSE,
                                               rownames=FALSE)

})

shinyApp(ui, server)

The main difference is using input$myDatatable_cells_selected which keeps the currently selected cells as opposed to input$myDatatable_cell_clicked which contains the clicked cell even when unselected, causing your issue.

Upvotes: 1

Related Questions