rstudio / DT

R Interface to the jQuery Plug-in DataTables
https://rstudio.github.io/DT/
Other
596 stars 182 forks source link

Using options > language breaks "DT-radio example" #679

Open phileas-condemine opened 5 years ago

phileas-condemine commented 5 years ago

I tried to make a slight change to the example app of @yihui https://yihui.shinyapps.io/DT-radio/ to add the language option from url ('//cdn.datatables.net/plug-ins/1.10.11/i18n/French.json') in renderDataTable, but the app no longer returned the months radio input. More details in the related question on SO : https://stackoverflow.com/questions/56780937/r-shiny-dt-with-radio-buttons-breaks-when-adding-language-option Someone found a trick to make it work by moving the Shiny.unbindAll & Shiny.bindAll in the initComplete script rather that in the callback.

Here is the code that doesn't work (simply adding the language option)

library(shiny)
library(DT)
shinyApp(
  ui = fluidPage(
    title = 'Radio buttons in a table',
    DT::dataTableOutput('foo'),
    verbatimTextOutput('sel')
  ),
  server = function(input, output, session) {
    m = matrix(
      as.character(1:5), nrow = 12, ncol = 5, byrow = TRUE,
      dimnames = list(month.abb, LETTERS[1:5])
    )
    for (i in seq_len(nrow(m))) {
      m[i, ] = sprintf(
        '<input type="radio" name="%s" value="%s"/>',
        month.abb[i], m[i, ]
      )
    }
    m
    output$foo = DT::renderDataTable(
      m, escape = FALSE, selection = 'none', server = FALSE,
      options = list(dom = 'tirp', paging = FALSE, ordering = FALSE
                     ,language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/French.json')
                     ),
      callback = JS("table.rows().every(function(i, tab, row) {
          var $this = $(this.node());
          $this.attr('id', this.data()[0]);
          $this.addClass('shiny-input-radiogroup');
        });
        Shiny.unbindAll(table.table().node());
        Shiny.bindAll(table.table().node());")
    )
    output$sel = renderPrint({
      str(sapply(month.abb, function(i) input[[i]]))
    })
  }
)

Here is my session_info()


    sessioninfo::session_info() - Session info ------------------------------------------------------------------ setting value
    version R version 3.6.0 (2019-04-26) os Windows 10 x64
    system x86_64, mingw32
    ui RStudio
    language (EN)
    collate French_France.1252
    ctype French_France.1252
    tz Europe/Paris
    date 2019-06-26

        Packages ---------------------------------------------------------------------- package * version date lib source
        assertthat 0.2.1 2019-03-21 [1] CRAN (R 3.6.0)
        cli 1.1.0 2019-03-19 [1] CRAN (R 3.6.0)
        crayon 1.3.4 2017-09-16 [1] CRAN (R 3.6.0)
        crosstalk 1.0.0 2016-12-21 [1] CRAN (R 3.6.0)
        digest 0.6.19 2019-05-20 [1] CRAN (R 3.6.0)
        DT * 0.7.1 2019-06-26 [1] Github (rstudio/DT@c6fd864) htmltools 0.3.6 2017-04-28 [1] CRAN (R 3.6.0)
        htmlwidgets 1.3 2018-09-30 [1] CRAN (R 3.6.0)
        httpuv 1.5.1 2019-04-05 [1] CRAN (R 3.6.0)
        jsonlite 1.6 2018-12-07 [1] CRAN (R 3.6.0)
        later 0.8.0 2019-02-11 [1] CRAN (R 3.6.0)
        magrittr 1.5 2014-11-22 [1] CRAN (R 3.6.0)
        mime 0.7 2019-06-11 [1] CRAN (R 3.6.0)
        packrat 0.5.0 2018-11-14 [1] CRAN (R 3.6.0)
        promises 1.0.1 2018-04-13 [1] CRAN (R 3.6.0)
        R6 2.4.0 2019-02-14 [1] CRAN (R 3.6.0)
        Rcpp 1.0.1 2019-03-17 [1] CRAN (R 3.6.0)
        rlang 0.3.4 2019-04-07 [1] CRAN (R 3.6.0)
        rstudioapi 0.10 2019-03-19 [1] CRAN (R 3.6.0)
        sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 3.6.0)
        shiny * 1.3.2 2019-04-22 [1] CRAN (R 3.6.0)
        sourcetools 0.1.7 2018-04-25 [1] CRAN (R 3.6.0)
        withr 2.1.2 2018-03-15 [1] CRAN (R 3.6.0)
        xtable 1.8-4 2019-04-21 [1] CRAN (R 3.6.0)
        yaml 2.2.0 2018-07-25 [1] CRAN (R 3.6.0)

Here is the fix (need to change ouput$foo only)

library(shiny)
library(DT)
shinyApp(
  ui = fluidPage(
    title = 'Radio buttons in a table',
    DT::dataTableOutput('foo'),
    verbatimTextOutput('sel')
  ),
  server = function(input, output, session) {
    m = matrix(
      as.character(1:5), nrow = 12, ncol = 5, byrow = TRUE,
      dimnames = list(month.abb, LETTERS[1:5])
    )
    for (i in seq_len(nrow(m))) {
      m[i, ] = sprintf(
        '<input type="radio" name="%s" value="%s"/>',
        month.abb[i], m[i, ]
      )
    }
    m
    output$foo = DT::renderDataTable(
      m, escape = FALSE, selection = 'none', server = FALSE,
      options = list(dom = 'tirp', paging = FALSE, ordering = FALSE,
                     initComplete = JS("function(settings,json){
                                     var table = settings.oInstance.api();
                                     Shiny.unbindAll(table.table().node());
                                     Shiny.bindAll(table.table().node());}")
                     ,language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/French.json')
      ),
      callback = JS("table.rows().every(function(i, tab, row) {
                  var $this = $(this.node());
                  $this.attr('id', this.data()[0]);
                  $this.addClass('shiny-input-radiogroup');
                });")
    )
    output$sel = renderPrint({
      str(sapply(month.abb, function(i) input[[i]]))
    })
  }
)

By filing an issue to this repo, I promise that

I understand that my issue may be closed if I don't fulfill my promises.

shrektan commented 4 years ago

Thanks for the reporting. I think the reason is documented in language.url. So yes, you need to provide the callback in options = list(initComplete = #your callback#).

Note that when this parameter is set, DataTables' initialisation will be asynchronous due to the Ajax data load. That is to say that the table will not be drawn until the Ajax request as completed. As such, any actions that require the table to have completed its initialisation should be placed into the initComplete callback.

I planed to update the example using your solution (or document this) but what surprise me is that your solution won't work if this line (,language = list(url = '//cdn.datatables.net/plug-ins/1.10.11/i18n/French.json')) gets removed.

I'll come back later.