Skip to content

How Extensions Work

DT2 loads extensions on demand. Instead of shipping all 15+ extensions to every page, only the CSS/JS for extensions you actually use are included.

There are two ways to specify extensions:

  1. Explicit — pass extensions = c("Buttons", "Select") to dt2()
  2. Auto-detection — DT2 scans your options list and infers which extensions are needed (this is the default when extensions = NULL)

Listing Available Extensions

dt2_extensions()
#>                        name version           dir
#> Buttons             Buttons   3.2.5       buttons
#> ColReorder       ColReorder   2.1.1    colreorder
#> ColumnControl ColumnControl   1.1.0 columncontrol
#> DateTime           DateTime   1.6.0      datetime
#> FixedColumns   FixedColumns   5.0.5  fixedcolumns
#> FixedHeader     FixedHeader   4.0.3   fixedheader
#> KeyTable           KeyTable  2.12.1      keytable
#> Responsive       Responsive   3.0.6    responsive
#> RowGroup           RowGroup   1.6.0      rowgroup
#> RowReorder       RowReorder   1.5.0    rowreorder
#> Scroller           Scroller   2.4.3      scroller
#> SearchBuilder SearchBuilder   1.8.4 searchbuilder
#> SearchPanes     SearchPanes   2.3.5   searchpanes
#> Select               Select   3.1.0        select
#> StateRestore   StateRestore   1.4.2  staterestore

Buttons (Export / Copy / Print)

The Buttons extension adds export and utility buttons.

dt2(mtcars[1:15, ], extensions = "Buttons", options = list(
  pageLength = 8,
  layout = list(
    topEnd = list(
      buttons = list("copy", "csv", "excel", "pdf", "print")
    )
  )
))

Grouped Buttons with Labels

dt2(iris[1:20, ], options = list(
  pageLength = 10,
  layout = list(
    topStart = "pageLength",
    topEnd = list(
      buttons = list(
        list(extend = "collection", text = "Export",
             buttons = list(
               list(extend = "copyHtml5", text = "Copy"),
               list(extend = "csvHtml5"),
               list(extend = "excelHtml5", title = "My Data"),
               list(extend = "pdfHtml5",   title = "My Data")
             )),
        list(extend = "colvis", text = "Columns")
      ),
      search = list(placeholder = "Filter...")
    ),
    bottomEnd = "paging"
  )
))

Note: DT2 auto-detected that layout contains buttons, so it loaded the Buttons extension automatically (no need to set extensions explicitly).

Select (Row Selection)

Enable row selection with the Select extension:

dt2(iris[1:20, ], options = list(
  select = list(style = "os", items = "row"),
  pageLength = 10
))

In Shiny, selected rows are available via input$<id>_state$selected.

Responsive

DT2 enables the Responsive extension by default. Tables fill 100% width and columns that don’t fit are collapsed into expandable child rows.

To disable for a specific table:

dt2(iris, responsive = FALSE, options = list(pageLength = 5))

To customise Responsive behaviour (e.g., disable child rows):

dt2(iris, options = list(
  responsive = list(details = FALSE)  # hide overflow silently
))

ColumnControl

ColumnControl adds per-column controls (order indicators, search dropdowns, column visibility) directly in the table header:

dt2(iris, options = list(
  pageLength = 8,
  columnControl = list("order", "searchDropdown",
    list(
      list(extend = "orderAsc",  text = "Sort Ascending"),
      list(extend = "orderDesc", text = "Sort Descending"),
      "spacer",
      list(extend = "colVisDropdown", text = "Toggle Columns")
    )
  ),
  ordering = list(indicators = FALSE, handler = FALSE)
))

FixedHeader

Keep the header visible while scrolling:

dt2(iris, options = list(fixedHeader = TRUE, pageLength = 50))

Combining Extensions

Extensions compose naturally. Here’s Buttons + Select + ColumnControl:

dt2(iris, options = list(
  pageLength = 8,
  select = list(style = "multi", items = "row"),
  layout = list(
    topEnd = list(
      buttons = list(
        list(extend = "selected",  text = "Selected Only"),
        list(extend = "selectAll", text = "Select All"),
        list(extend = "selectNone", text = "Deselect"),
        "spacer",
        list(extend = "csvHtml5", exportOptions = list(modifier = list(selected = TRUE)))
      )
    )
  ),
  columnControl = list("order", "searchDropdown"),
  ordering = list(indicators = FALSE, handler = FALSE)
))

Adding New Plugins

To add a DataTables plugin not yet in the registry:

  1. Add version variable and download commands in tools/get-dt2-libs.sh
  2. Register it in R/dt2_extensions.R (.dt2_extension_registry())
  3. Add auto-detection rules in .dt2_detect_extensions()
  4. Add npm mapping in R/dt2_check_updates.R (.dt2_npm_map())
  5. Run bash tools/get-dt2-libs.sh to download the files
  6. Test with dt2(data, extensions = "YourPlugin")

The declarative registry in dt2_extensions.R is the single source of truth for extension metadata (version, JS files, CSS files, dependencies).

Updating Library Versions

Check for newer versions of all bundled JS/CSS libraries:

Library            Installed   Latest      Compat.     Status
-----------------------------------------------------------------
DataTables         2.3.4       2.3.7       2.3.7       ⚠️  UPDATE
jQuery             3.7.0       4.0.0       3.7.1       🔒 PINNED [pin: 3.x]
Buttons            3.2.5       3.2.6       3.2.6       ⚠️  UPDATE
...

If you are developing DT2 (working from the source tree), apply compatible updates automatically:

dt2_update_libs()                    # patch files + download new JS/CSS
dt2_update_libs(dry_run = TRUE)      # preview without changing anything
dt2_update_libs(download = FALSE)    # patch R files only (manual download)

Version constraints prevent incompatible upgrades:

  • jQuery pinned to 3.x (DataTables 2 requires jQuery 3)
  • pdfmake pinned to 0.2.x (0.3.x has breaking changes)
  • Bootstrap pinned to 5.x

Libraries marked as PINNED are up to date within their allowed range. Edit .dt2_version_constraints() to change the allowed ranges.