Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Checkboxes in DT shiny

Tags:

checkbox

r

dt

shiny

I'm trying to make checkboxs into DT table and collect information about checked rows.
My code below

shinyApp(
  ui = fluidPage(
    fluidRow(
      verbatimTextOutput("value1"),
      column(12,
             DT::dataTableOutput('table'),  tags$script(HTML('$(document).on("click", "input", function () {
                       var checkboxes = document.getElementsByName("selected");
                       var checkboxesChecked = [];
                       for (var i=0; i<checkboxes.length; i++) {
                       if (checkboxes[i].checked) {
                       checkboxesChecked.push(checkboxes[i].value);
                      }
                      }
                     Shiny.onInputChange("checked_rows",checkboxesChecked);  })'))
      ))),
  server = function(input, output) {
    library(DT)
    library(glue)
    output$value1 <- renderPrint({ input$checked_rows }) 

    output$table <- DT::renderDataTable({
      iris$checked<-''
      iris$checked[2:5]<-'checked=\"checked\"'
      iris[["Select"]]<-glue::glue('<input type="checkbox" name="selected" {iris$checked} value="{1:nrow(iris)}"><br>')
      datatable(iris,escape=F,rownames=F,  class = 'cell-border compact', 
                options=list(ordering=T,autowidth=F,scrollX = TRUE,
                columnDefs = list(list(className = 'dt-center', targets = "_all"))
                ),
                selection="none"
      ) })})

enter image description here

All looking good, but:
1. when I make a choice in checkboxes and change the page, all data from the previous page disappears.
2. Also, as you can see on verbatimTextOutput ("value1"), it's worth selecting only checkboxes from the current page. How can I poll the entire table, and not just the page that I see?

Thanks!

like image 638
jyjek Avatar asked Mar 28 '18 20:03

jyjek


1 Answers

As you can see from the below picture, the datatables library (the javascript library that the DT package uses to display the nice tables) only render parts of the table that the current page displays (there're only 10 <tr> tags but the table contains 150 rows).

That's reason your script cannot count correctly because there're only parts of the table in the DOM.

Moreover, the DT package enables the server-side process mode by default (see the help by calling ?DT::renderDT in R or datatables.net/manual/server-side), which means that the browser will not only be feed with the data being displayed. In other words, it's not even possible to count them correctly in the browser if you enabled the server-side processing mode.

The screenshot from the developer tools of Chrome

However, there're alternative ways exist:

  1. Use the param selection = "multiple": although it doesn't give you a checkbox but it's basically what you need;
  2. If you do want a checkbox, you may find rstudio/DT#93comment or shinyapps/DT-radio helpful;
  3. Or you can disable the server-processing mode and write a listener to change the table data whenever the checkboxes get clicked. And count it like below.

code

$(document).on("click", "input", function () {
      var data = table.data();
      var res = [];
      var elem;
      for (var i=0; i < data.length; i++) {
        elem = $.parseHTML(data[i][6])[0];
        if (elem.checked) {
          res.push(elem.value);
        }
      }
      Shiny.onInputChange("checked_rows", res);  }
  )
like image 170
Shrek Tan Avatar answered Oct 19 '22 15:10

Shrek Tan