Search code examples
javascripthtmlrshinydt

How to assign values to DT checkboxes?


Can input type checkbox be assigned a value TRUE/FALSE via javascript in a shiny app? For example, I have a reactive data table:

data:vals<-reactiveValues()
  vals$Data<-data.table(
    Brands=paste0("Brand",1:200000),
    Forecasted_Growth=sample(1:200000,200000),
    Last_Year_Purchase=round(rnorm(200000,1000,1000)^2),
    Contact=paste0("Brand",1:200000,"@email.com"),
    YN=sample(rep(c("TRUE","FALSE"),each=100000),200000,replace=FALSE)
  )

I would like to assign the value of each YN to a checkbox when the app loads. Later I can manipulate the checked rows. I've tried to use HTML like this to assign the value of each YN to each checkbox but it doesn't work:

DT[["Select"]]<-paste0('<input type="checkbox" name="row_selected',1:nrow(vals$Data),'" value=',vals$Data$YN,'><br>')

Then I will use this JS to get the values later:

tags$script(HTML('$(document).on("click", "input", function () {
  var checkboxes = document.getElementsByName("row_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);
      })')),

Is it possible to assign values to checkboxes in that way? I'm trying to modify an example from here:

https://github.com/AntoineGuillot2/ButtonsInDataTable/


Solution

  • The reason why your approach does not work is that you assign the boolean represented by YN to the value attribute. Instead (for HTML 5), you have to use checked if TRUE and omit checked otherwise.

    So an example df could look like this:

    > df
                                               Select    YN  mpg cyl disp  hp
    Mazda RX4         <input type="checkbox" checked>  TRUE 21.0   6  160 110
    Mazda RX4 Wag            <input type="checkbox" > FALSE 21.0   6  160 110
    Datsun 710        <input type="checkbox" checked>  TRUE 22.8   4  108  93
    Hornet 4 Drive    <input type="checkbox" checked>  TRUE 21.4   6  258 110
    Hornet Sportabout        <input type="checkbox" > FALSE 18.7   8  360 175
    

    And when the app is started, it would look so:

    enter image description here

    Minimal example:

    library(shiny)
    library(DT)
    library(dplyr)
    
    df <- head(mtcars[1:4], n = 5) |>
      mutate(YN = c(T, F, T, T, F), .before = mpg) |>
      mutate(Select = paste0('<input type="checkbox" ',
                             ifelse(YN == TRUE, 'checked', ''),
                             '>'),
             .before = YN)
    
    js <- c(
      "table.rows().every(function(i, tab, row) {",
      "    var $this = $(this.node());",
      "    $this.attr('id', this.data()[0]);",
      "    $this.addClass('shiny-input-checkbox');",
      "});",
      "Shiny.unbindAll(table.table().node());",
      "Shiny.bindAll(table.table().node());"
    )
    
    ui <- fluidPage(DT::dataTableOutput("example"))
    
    server <- function(input, output, session) {
      rv <- reactiveValues(df = df)
      
      output$example <- DT::renderDataTable(rv$df,
                                            callback = JS(js),
                                            escape = FALSE,
                                            server = FALSE)
    }
    
    shinyApp(ui, server)