R Shiny Datatable: prevent deselection of an already selected row when you click on it again

Viewed 907

R (ver 3.4.1) I am working with DT (ver 0.4) package in shiny (ver 1.0.5) and have a need where I want to prevent the deselection of an already selected row when user clicks on it again. For example in below image if user clicks on row 3 again it should not get deselected. However if user selects a new row then that new row gets selected while the earlier row gets deselected.

I guess what I need is for datatable to completely ignore a click-event on an already selected row.

If user clicks on row 3 again it should not get deselected but if he clicks on a new row then that new row should get selected while deselecting the old one

I tried using shinyjs::onclick as shown below but is not ideal as it seems to "de-select & re-select" the selected row (the blue highlight disappears and reappears when clicked on again) rather than preventing deselection.

library(shiny)
library(DT)
library(shinyjs)

shinyApp(
  ui <- shinyUI(
    fluidPage(
      shinyjs::useShinyjs(),
      DTOutput("test")
    )
  ),  
  server <- shinyServer(function(input, output, session) {

    output$test <- renderDT({
      datatable(head(iris), selection = 'single')
    })    
    shinyjs::onclick("test",
               selectRows(dataTableProxy("test"), selected = input$test_rows_selected)
             )    
  })
)

I was wondering if there was an easy way to do this. Thanks!

2 Answers

Try using pointer-events: none in css:

table.dataTable tbody tr.selected {
  pointer-events: none
}

The only limitation is it prevents the whole hover/clicking event on the currently selected row, so you can't use it on columns with hoverable/clickable HTML contents.

I hope it helps!

This is only a partial solution (see the edit below for a fully working solution). It works only when you click twice on the row. At the third click, the row is deselected, I don't know why. Maybe an expert in datatables could help.

library(shiny)
library(DT)

shinyApp(
  ui <- shinyUI(
    fluidPage(
      DTOutput("test")
    )
  ),  
  server <- shinyServer(function(input, output, session) {

    output$test <- renderDT({
      datatable(head(iris), selection = list(mode="single", target="row"), 
                extensions = c("Select"), options = list(select=TRUE),
                callback = JS("
table.on('user-select', 
function (e, dt, type, cell, originalEvent) {
  if ($(cell.node()).parent().hasClass('selected')) {
    e.preventDefault();
  }
});"))
    })    
  })
)

EDIT

I've found a solution (I don't fully understand it).

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

    output$test <- renderDT({
      datatable(head(iris), selection = list(mode="single", target="row", info=FALSE), 
                extensions = c("Select"), options = list(select=TRUE),
                callback = JS("
  table.on('user-select', 
    function (e, dt, type, cell, originalEvent) {
      if ($(cell.node()).parent().hasClass('selected') || e.result === undefined) {
        e.preventDefault();
        $(cell.node()).parent().addClass('selected')
        return false;
      }
    });")
      )
    })    
  })
Related