Experimental support for server-side data processing in Shiny apps. Use
reactable(server = TRUE) to render a table using server-side data processing in Shiny.
Server-side data processing requires the V8 package, which is not installed
with reactable by default. (#22)
library(shiny)
library(reactable)
tbl <- reactable(
mtcars,
server = TRUE
)
ui <- fluidPage(
reactableOutput("tbl")
)
server <- function(input, output) {
output$tbl <- renderReactable({
tbl
})
}
shinyApp(ui, server)
reactable() gains a virtual argument to enable virtual scrolling. Virtual scrolling renders only the visible rows on screen, allowing you to scroll through large tables without performance issues. (#203)
reactable(
data.frame(x = 1:100000, y = rnorm(100000)),
pagination = FALSE,
virtual = TRUE,
height = 500
)
New Reactable.toggleSortBy() and Reactable.setSortBy() methods in the JavaScript API to programmatically control column sorting. toggleSortBy() toggles sort on a single column (cycling between ascending and descending), while setSortBy() sets the full sort state declaratively. Also available via updateReactable(sortBy = ...) in Shiny. (#316, #322)
New Reactable.toggleRowSelected(), Reactable.setRowsSelected(), and Reactable.toggleAllRowsSelected() methods in the JavaScript API to programmatically control row selection. Additionally, rowInfo.toggleRowSelected() and cellInfo.toggleRowSelected() are now available in JavaScript render and style functions. (#322, #394, #412)
New Reactable.gotoPage() and Reactable.setPageSize() methods in the JavaScript API to change the current page or page size. (#322)
JSON serialization of data can now be customized using the reactable.json.func option. This is an experimental feature for advanced use only, and intentionally undocumented outside of NEWS. reactable may change how data is serialized between versions and does not guarantee stability. See reactable:::toJSON as a reference for how data is currently serialized. (@khusmann, #415)
Example usage:
# Use yyjsonr as a faster alternative for JSON serialization. Note that this is not 1:1 consistent with
# jsonlite, and several edge cases are not handled here, including data frames with 1 row, datetimes, and NULLs.
options(reactable.json.func = function(x, ...) {
result <- yyjsonr::write_json_str(
x,
opts = yyjsonr::opts_write_json(
dataframe = "columns",
auto_unbox = TRUE,
num_specials = "string"
)
)
class(result) <- "json"
result
})
JS() not working when htmlwidgets 1.6.3 or later is installed. (#348)reactableTheme(), stripedColor and highlightColor now work when using sticky columns. (@grcatlin, #401)meta values change. (@khusmann, #416)pagination = FALSE with showPagination = TRUE and filtering out all rows.core-js is no longer included in the HTML dependencies. This was required to support IE 11 and old versions of the RStudio Viewer. (#245)meta is now converted to JavaScript in the same way as data, using reactable's internal JSON serialization function rather than htmlwidgets's JSON serialization function. This should only be a breaking change in rare cases, as the major difference is that numeric NA, NaN, Inf, and -Inf values are now serialized as strings and preserved, rather than always being converted to null. (@khusmann, #415)r-devel-linux-x86_64-fedora-clang platform. (#308)htmlwidgets 1.6.0 or later is installed.
In general, fixed rendering of any Shiny HTML tags with duplicate attributes. (@tomsing1, #306)reactable(static = TRUE) to render a table to static HTML, or options(reactable.status = TRUE)
to enable static rendering globally. With static rendering, tables are pre-rendered
to their initial HTML so they appear immediately without any flash of content.
Tables are then made interactive and subsequently rendered by JavaScript as needed.
Static rendering requires the V8 package, which is not installed with reactable
by default. Learn more in the Static Rendering article.reactable() gains a meta argument to pass arbitrary data from R to JavaScript
render functions and style functions. Custom metadata can be accessed using the state.meta property, and updated
using updateReactable() in Shiny or Reactable.setMeta() in the JavaScript API. See examples of using
custom metadata for custom rendering
or custom metadata for conditional styling.
(#255)Reactable.onStateChange()
method in the JavaScript API that sets up a function to be called whenever the
table state changes. (#265)Reactable.setData()
method in the JavaScript API for updating the table data. (#278)Reactable.downloadDataCSV()
in the JavaScript API now supports an additional options argument to change the field or decimal separator,
include specific columns, and exclude column headers. (#239, #293)Reactable.getDataCSV()
method in the JavaScript API to get the table data as a CSV string.Reactable.toggleHideColumn()
and Reactable.setHiddenColumns()
methods in the JavaScript API to toggle or set hidden columns. JavaScript render functions and style functions
also receive a new state.hiddenColumns property for the hidden columns in the table. (#246)getReactableState() now includes the current sorted columns. (#265)rem/em instead of px). The documentation site uses the default
root font size of 16px, so examples may look different on pages that change the
root font size. For example, Bootstrap 3 sets a default root font size of 10px,
so you may need to adjust the rem values before adapting examples to your site.
(Bootstrap 4 and above no longer change the default root font size).cellInfo.index or rowInfo.index property for aggregated cells and rows.
(#250)NULL values in list-columns now correctly appear as missing values instead of
[object Object]. NULL values are now represented as null values in JavaScript
instead of an empty object like {}.reactableTheme() styles no longer override custom user CSS in the
HTML document <head>.getReactableState() now accepts multiple values in its name argument to return a subset of state values.reactable() now respects htmlwidget::sizingPolicy()'s viewer.fill and browser.fill and fills the
RStudio Viewer pane by default. (@cpsievert, #280)reactable() on a dplyr grouped data frame ( dplyr::group_by() or grouped_df) with rownames = TRUE
no longer adds a stringsAsFactors column to the table. (@daattali, #283)NA values are now represented as null in JavaScript instead of an "NA" string.
Numeric NaN, Inf, and -Inf values are now represented as NaN, Infinity, and -Infinity
in JavaScript instead of "NaN", "Inf", and "-Inf" strings. (@daattali, #261)
function(cellInfo) {
// Old
cellInfo.value // "NA", "NaN", "Inf", "-Inf"
// New
cellInfo.value // null, NaN, Infinity, -Infinity
}
This release upgrades to a new major version of React Table (#35), which brings many new features, improvements, and bug fixes. reactable has been largely rewritten to take advantage of React Table's new approach as a flexible table utility rather than a table component.
This means it'll be easier to add new custom features, customize styling and markup, and maintain reactable in the future. Most of the features and fixes in this release would not have been possible or easy to do without this upgrade.
Backward compatibility was kept where possible, but note that there are several breaking changes, particularly around the JavaScript API.
vAlign and headerVAlign
arguments in colDef(), and the new headerVAlign argument in colGroup()
(#142,
#177).sticky argument in colDef()
and colGroup() (#19,
#72,
#141).reactable() gains a searchMethod argument to use a custom JavaScript function
for global table searching (#222).colDef() gains a filterMethod argument to use a custom JavaScript function
for column filtering (#9,
#90,
#145).colDef() gains a filterInput argument to render a custom filter input for
column filtering (#9).reactable() gains a paginateSubRows argument to include grouped sub rows
in pagination. This is recommended for grouped tables with a large number of rows
where expanded rows may not all fit on one page.colDef() gains a grouped argument to customize rendering for grouped cells
in groupBy columns (#33,
#94,
#148).rowInfo.expanded and cellInfo.expanded indicating whether the row is expandedcellInfo.selected indicating whether the cell's row is selectedstate.page, state.pageSize, and state.pages for the current page index,
page size, and number of pages in the tablecellInfo.filterValue and column.filterValue for the column filter value, and
column.setFilter to set the filter valuestate.filters for the column filter valuesstate.searchValue for the table search valuestate.selected for the selected row indicesstate argument to access the table state
(#88). Custom cell click actions also
now receive a state argument.colDef() gains a searchable argument to enable or disable global table
searching. Columns can be excluded from searching using colDef(searchable = FALSE),
and hidden columns can be included in searching using colDef(searchable = TRUE)
(#217).Several properties and arguments have been renamed or moved for consistency with the rest of the API. These properties were not removed unless they were very rarely used, so most code should continue to work upon upgrading.
rowInfo.row property is now deprecated, and has been renamed to
rowInfo.values. rowInfo.row remains supported, but replace usages with
rowInfo.values when possible.
// Old
function(rowInfo) {
rowInfo.row
}
// New
function(rowInfo) {
rowInfo.values
}
colInfo.column and colInfo.data properties in header and cell render
functions are now deprecated. The colInfo object now contains all of the same
properties as colInfo.column, and is now referred to as column in the documentation.
When possible, replace usages of colInfo with column, colInfo.column
with column, and colInfo.data with state.sortedData (current rows after sorting
and filtering) or state.data (the original data).
// Old
function(colInfo) {
colInfo.column.id
colInfo.data
}
// New
function(column, state) {
column.id
state.sortedData
}
state.expanded property has been removed. To check whether a row is
expanded, use rowInfo.expanded instead.
// Old
function(rowInfo, column, state) {
if (state.expanded[rowInfo.index]) { // row is expanded ... }
}
// New
function(rowInfo, column, state) {
if (rowInfo.expanded) { // row is expanded ... }
}
rowInfo.page and cellInfo.page properties have been removed. To get
the current page index of the table, use state.page instead.
// Old
function(rowInfo, column, state) {
rowInfo.page
}
// New
function(rowInfo, column, state) {
state.page
}
function(cellInfo) {
// Old
cellInfo.value // 2022-05-22T19:30:00
// New
cellInfo.value // 2022-05-22T19:30:00Z
// With a UTC time, it's much easier to format dates in the user's local time
return new Date(cellInfo.value).toLocaleString()
}
jsonlite::toJSON(auto_unbox = TRUE)).
For example, list(x = 1) in R is now represented as {x: 1} in JavaScript
instead of {x: [1]}.columnGroups and groupBy arguments are provided in reactable(),
groupBy columns are no longer added to a column group automatically
(#87).defaultGroupHeader argument in reactableLang() is now deprecated and
no longer used. Use the columnGroups argument in reactable() to customize
the column group header for groupBy columns.detailsCollapseLabel, deselectAllRowsLabel, deselectAllSubRowsLabel,
and deselectRowLabel arguments in reactableLang() are now deprecated and
no longer used (#167).groupBy and row details columns
(#71).reactableTheme(cellPadding = "...") (#248,
#142,
#177).show = FALSE as a default value in defaultColDef() now works
(@csgillespie, #105).
Setting sortNALast, html, and na to their default values in
defaultColDef() also now works.pageSizeOptions in reactable() now works.reactable(), defaultExpanded = TRUE now expands all rows in the table,
not just rows on the first page.reactable(), defaultExpanded = TRUE now works when column groups are present.groupBy columns, aggregate functions
could take aggregated values which could produce inaccurate calculations
(e.g., when calculating the mean of values)."max" and "min" aggregate functions now work on dates, date-times,
and strings (#130).reactable() now works for data frames with difftime objects and objects
with custom classes (#164).colFormat() now formats dates and times in the user's time zone, rather than
ignoring time zones.aria-expanded attribute to indicate expanded
or collapsed state, and use "Toggle details" as their default label
(#167).reactableLang() gains the groupExpandLabel argument to customize the
accessible label for row group expand buttons
(#167).rowHeader argument in colDef(). Cells in the row names column are
automatically marked up as row headers (#167).reactableTheme(), filterInputStyle now applies correctly when rerendering
a table in Shiny (#186).reactableTheme(), cellPadding now applies to column group headers correctly.[ or ]) in their column name now render correctly
(#187).reactable(pagination = FALSE) now works correctly
on table data updates (#214).onclick
(#150).updateReactable() gains a data argument to update the data of a reactable
instance in Shiny (#49).defaultSelected now works correctly with Crosstalk linked selection.SharedData objects with zero or one rows.colFormat() now always formats numbers as a localized string when locales
is specified.reactableTheme(tableBodyStyle = list(flex = "auto")).reactable() now supports linked selection and filtering with Crosstalk-compatible
HTML widgets (#46).reactable() gains a theme argument to customize the default styling of a table.reactable() gains a language argument to customize the language strings in a table
(#24).reactable() gains a defaultSelected argument to set default selected rows.reactable() gains a defaultExpanded argument to set default expanded rows
(#23).updateReactable() function to update the selected rows, expanded rows, or
current page of a reactable instance in Shiny (#20).getReactableState() function to get the state of a reactable instance in Shiny
(#20).colDef() gains a "median" aggregate function to calculate the median of numbers
(#30).".selection" as the column name
(#19).reactable(), the rowClass, rowStyle, and details JavaScript functions
now receive a rowInfo.selected property indicating whether the row is selected
(#20).selectionId argument in reactable() will be deprecated in a future release.
Use getReactableState() to get the selected rows of a table in Shiny instead.colFormat(date = TRUE) now formats YYYY-MM-DD dates correctly (#38).colFormat(percent = TRUE) now works correctly when viewing tables in IE11.colDef(), the class and style R functions now handle list-columns correctly.