Introduction
The JavaScript API lets you manipulate and access tables from JavaScript. You can use this to create custom interactive controls for your table without the use of Shiny, or add cross-widget interactions beyond what Crosstalk provides.
Common use cases for the JavaScript API include:
- Export buttons to download table data to a CSV file
- Custom filter inputs located outside of the table
- Toggle buttons for row grouping or row expansion
Using the JavaScript API
To use the JavaScript API, your table must first have a unique ID that distinguishes it from other tables:
-
For tables in static documents (e.g., R Markdown), add an ID through the
elementId
argument inreactable()
: -
For tables in Shiny apps, the ID will be the Shiny output ID specified in
reactableOutput()
. For example, the table in this app usescars_table
as its ID:library(shiny) ui <- fluidPage( reactableOutput("cars_table") ) server <- function(input, output) { output$cars_table <- renderReactable({ reactable(MASS::Cars93) }) } shinyApp(ui, server)
Once your table has an ID, you can use any of the
Reactable
JavaScript functions with that table ID. For
example, to download data from the cars-table
table to a
CSV file, the JavaScript code would look like this:
// Download the "cars-table" data to a CSV file named 'cars.csv'
.downloadDataCSV('cars-table', 'cars.csv') Reactable
To try this out interactively, you can open your browser’s developer tools and run this function in the JavaScript console.
Creating custom interactive controls
Most users will likely want to use the JavaScript API through an
interactive control, such as a button, so they could decide when to
download the table data. Using HTML, you can create a
<button>
element with an onclick
action
that calls the Reactable
JavaScript function.
This example uses the htmltools
package to render a CSV
download button. You can copy this code into an R console to view the
output:
library(htmltools)
htmltools::browsable(
tagList(
tags$button("Download as CSV", onclick = "Reactable.downloadDataCSV('cars-table', 'cars.csv')"),
reactable(MASS::Cars93[, 1:5], elementId = "cars-table")
)
)
Note: htmltools::browsable()
is a
convenient way to view the rendered HTML when copying code into the
console. It isn’t required to render HTML in R Markdown documents or
Shiny apps.
To reuse this button in other tables, you can also convert it into a function that generates download buttons:
library(htmltools)
csvDownloadButton <- function(tableId, label = "Download as CSV", filename = "data.csv") {
htmltools::tags$button(
label,
onclick = sprintf("Reactable.downloadDataCSV('%s', '%s')", tableId, filename)
)
}
htmltools::browsable(
tagList(
csvDownloadButton("cars-table", "Download as CSV", filename = "cars.csv"),
reactable(MASS::Cars93[, 1:5], elementId = "cars-table")
)
)
For more examples of custom controls that use the JavaScript API, check out the JavaScript API examples.
JavaScript API Reference
Reactable.downloadDataCSV()
Downloads the table data to a CSV file. The downloaded file will be
named data.csv
by default, but you can customize this using
the optional filename
argument.
The downloaded data will include any filters that have been applied, and exclude any sorting or grouping. Hidden columns will also be included, but this may be customizable in the future.
For further customization, you can use the options
argument to only include specific columns, exclude column headers,
change the field separator, or change the decimal separator (new in
v0.4.0).
.downloadDataCSV(
Reactable: string,
tableId= "data.csv",
filename // New in v0.4.0
?: {
options: string[],
columnIds: true,
headers: ',',
sep: '.'
dec
} )
Examples
// Download table data to a file named data.csv
.downloadDataCSV('cars-table')
Reactable
// Download table data to a file named cars93.csv
.downloadDataCSV('cars-table', 'cars93.csv')
Reactable
// Download table data to a tab-separated values file
.downloadDataCSV('cars-table', 'cars93.tsv', { sep: '\t' })
Reactable
// Download table data with custom columns and headers excluded
.downloadDataCSV('cars-table', 'cars93.csv', {
ReactablecolumnIds: ['Model', 'Type'],
headers: false
})
Reactable.getDataCSV()
New in v0.4.0
Gets the table data as a CSV string. Same as Reactable.downloadDataCSV()
but does not download the data.
.getDataCSV(
Reactable: string,
tableId?: {
options: string[],
columnIds: true,
headers: ',',
sep: '.'
dec
} )
Reactable.setSearch()
Sets the search value of a table. To clear the search, set the value
to undefined
.
.setSearch(
Reactable: string,
tableId: any
value )
Reactable.setFilter()
Sets the filter value of a column. To clear the column filter, set
the value to undefined
.
.setFilter(
Reactable: string,
tableId: string,
columnId: any
value )
Reactable.setAllFilters()
Sets all column filter values in the table. To clear the column
filters, set filters
to an empty array,
[]
.
.setAllFilters(
Reactable: string,
tableId: Array<{ id: string, value: any }>
filters )
Examples
// Set the column filters for the "Type" column
.setAllFilters('cars-table', [{ id: 'Type', value: 'midsize' }])
Reactable
// Set the column filters for the "Type" and "Model" columns
.setAllFilters('cars-table', [
Reactableid: 'Type', value: 'midsize' },
{ id: 'Model', value: 'legend' }
{
])
// Clear all column filters
.setAllFilters([]) Reactable
Reactable.toggleGroupBy()
Toggles the groupBy
state for a column between grouped
and ungrouped. To enable or disable grouping explicitly, set the
optional isGrouped
argument to true
or
false
.
.toggleGroupBy(
Reactable: string,
tableId: string,
columnId?: boolean
isGrouped )
Reactable.setGroupBy()
Sets the groupBy
columns for the table. To clear the
groupBy
columns, set columnIds
to an empty
array, []
.
.setGroupBy(
Reactable: string,
tableId: string[]
columnIds )
Reactable.toggleAllRowsExpanded()
Toggles the expanded state of all rows in the table between expanded
and collapsed. To expand or collapse rows explicitly, set the optional
isExpanded
argument to true
or
false
.
.toggleAllRowsExpanded(
Reactable: string,
tableId?: boolean
isExpanded )
Reactable.setMeta()
New in v0.4.0
Sets the custom metadata for the table. meta
can either
be an object with new values, or a function that takes the previous
metadata object and returns new values.
New values are merged into the current metadata, so only the values
specified in meta
will be updated. To clear all metadata,
set meta
to undefined
.
.setMeta(
Reactable: string,
tableId?: object | Function
meta )
Examples
// Set metadata, updating the values for the `count`, `enabled`, and `formatter` properties
.setMeta('cars-table', { count: 123, enabled: true, formatter: value => '$' + value })
Reactable
// Set metadata using a function that increments `count` and toggles an `enabled` boolean
.setMeta('cars-table', prevMeta => {
Reactablereturn { count: prevMeta.count + 1, enabled: !prevMeta.enabled }
})
// Clear metadata
.setMeta('cars-table', undefined) Reactable
Reactable.toggleHideColumn()
New in v0.4.0
Toggles the hidden state for a column between hidden and shown. To
hide or show a column explicitly, set the optional isHidden
argument to true
or false
.
.toggleHideColumn(
Reactable: string,
tableId: string,
columnId?: boolean
isHidden )
Reactable.setHiddenColumns()
New in v0.4.0
Sets the hidden columns for the table. columnIds
can
either be an array of column IDs, or a function that takes the previous
hidden column IDs and returns new column IDs.
To clear the hidden columns, set columnIds
to an empty
array, []
.
.setHiddenColumns(
Reactable: string,
tableId: string[] | Function
columnIds )
Examples
// Set the hidden columns to "Type" and "Manufacturer"
.setHiddenColumns('cars-table', ['Type', 'Manufacturer'])
Reactable
// Set hidden columns using a function that adds "Type" to the existing hidden columns
.setMeta('cars-table', prevHiddenColumns => {
Reactablereturn prevHiddenColumns.concat('Type')
})
// Clear the hidden columns
.setHiddenColumns('cars-table', []) Reactable
Reactable.setData()
New in v0.4.0
Updates the table data. data
can either be in row or
column format. In row format, data
is an array of row
objects. In column format, data
is an object containing
arrays of column values. data
should have all the same
columns as the original table data.
When updating data, the selected rows and current page will reset by default. All other state will persist, including sorting, filtering, and grouping state.
.setData(
Reactable: string,
tableId: Array<object> | object
data )
Reactable.getState()
Gets the current state of a table.
.getState(tableId: string) Reactable
Value
An object with the following properties:
Property | Example | Description |
---|---|---|
sorted
|
[{ id: "Petal.Length", desc: true }, ...]
|
columns being sorted in the table |
page
|
2
|
page index (zero-based) |
pageSize
|
10
|
page size |
pages
|
5
|
number of pages |
filters
|
[{ id: "Species", value: "petal" }]
|
column filter values |
searchValue
|
"petal"
|
table search value |
selected
|
[0, 1, 4]
|
selected row indices (zero-based) |
pageRows
|
[{ Petal.Length: 1.7, Species: "setosa" }, ...]
|
current row data on the page |
sortedData
|
[{ Petal.Length: 1.7, Species: "setosa" }, ...]
|
current row data in the table (after sorting, filtering, grouping) |
data
|
[{ Petal.Length: 1.7, Species: "setosa" }, ...]
|
original row data in the table |
meta
|
{ custom: 123 }
|
custom table metadata from
reactable()
(new in v0.4.0)
|
hiddenColumns
|
["Petal.Length"]
|
columns being hidden in the table |
Reactable.onStateChange()
New in v0.4.0
Sets up a function that will be called whenever the table state changes.
listenerFn
should be a function that takes the current
table state, an object with properties described at state properties.
Reactable.onStateChange()
can only be run when the table
has finished rendering, which isn’t guaranteed to happen at page load
time. To ensure that the table is ready before running
Reactable.onStateChange()
, you can either use
htmlwidgets::onRender()
for static widgets and Shiny
outputs, or htmlwidgets::onStaticRenderComplete()
for
static widgets only.
.onStateChange(
Reactable: string,
tableId: Function
listenerFn )
Value
Reactable.onStateChange
returns a function that can be
called to cancel the listener function.
Examples
.onStateChange('cars-table', state => {
Reactableconsole.log('selected rows:', state.selected)
})
// Cancel the listener function
const cancel = Reactable.onStateChange('cars-table', listenerFn)
cancel()
Static widgets
library(htmltools)
data <- MASS::Cars93[, c("Manufacturer", "Model", "Type", "Price")]
browsable(
tagList(
"Table state:",
tags$pre(id = "tbl-state", "{}"),
reactable(
data,
searchable = TRUE,
selection = "multiple",
onClick = "select",
elementId = "tbl"
),
htmlwidgets::onStaticRenderComplete("
Reactable.onStateChange('tbl', state => {
const { selected, sorted, searchValue, pageIndex } = state
document.getElementById('tbl-state').textContent = JSON.stringify({
selected,
sorted,
searchValue,
pageIndex
})
})
")
)
)
Shiny outputs
library(shiny)
data <- MASS::Cars93[, c("Manufacturer", "Model", "Type", "Price")]
ui <- fluidPage(
reactableOutput("tbl"),
verbatimTextOutput("tbl_state")
)
server <- function(input, output) {
output$tbl <- renderReactable({
tbl <- reactable(data, searchable = TRUE)
htmlwidgets::onRender(tbl, "() => {
Reactable.onStateChange('tbl', state => {
const { sorted, searchValue } = state
Shiny.setInputValue('tbl_state', { sorted, searchValue })
})
}")
})
output$tbl_state <- renderPrint({
writeLines("Table state:\n")
print(input$tbl_state)
})
}
shinyApp(ui, server)