Skip to contents

New in v0.3.0


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

Example: CSV download button


    tags$button("Download as CSV", onclick = "Reactable.downloadDataCSV('cars-table')"),

      MASS::Cars93[, 1:5],
      defaultPageSize = 5,
      elementId = "cars-table"

Using the JavaScript API

To use the JavaScript API, your table must first have a unique ID that distinguishes it from other tables:

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'
Reactable.downloadDataCSV('cars-table', 'cars.csv')

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:


    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:


csvDownloadButton <- function(tableId, label = "Download as CSV", filename = "data.csv") {
    onclick = sprintf("Reactable.downloadDataCSV('%s', '%s')", tableId, filename)

    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


Downloads the table data to a CSV file. The downloaded file is 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.

  tableId: string,
  filename = "data.csv"


// Download table data to a file named data.csv

// Download table data to a file named cars93.csv
Reactable.downloadDataCSV('cars-table', 'cars93.csv')


Sets the search value of a table. To clear the search, set the value to undefined.

  tableId: string,
  value: any


// Set the search value to "midsize"
Reactable.setSearch('cars-table', 'midsize')

// Clear the search value
Reactable.setSearch('cars-table', undefined)


Sets the filter value of a column. To clear the column filter, set the value to undefined.

  tableId: string,
  columnId: string,
  value: any


// Set the filter value of the "Type" column to "midsize"
Reactable.setFilter('cars-table', 'Type', 'midsize')

// Clear the filter value of the "Type" column
Reactable.setFilter('cars-table', 'Type', undefined)


Sets all column filter values in the table. To clear the column filters, set filters to an empty array, [].

  tableId: string,
  filters: Array<{ id: string, value: any }>


// Set the column filters for the "Type" column
Reactable.setAllFilters('cars-table', [{ id: 'Type', value: 'midsize' }])

// Set the column filters for the "Type" and "Model" columns
Reactable.setAllFilters('cars-table', [{ id: 'Type', value: 'midsize' }, { id: 'Model', value: 'legend' }])

// Clear all column filters


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.

  tableId: string,
  columnId: string,
  isGrouped?: boolean


// Toggle groupBy state for the "Type" column
Reactable.toggleGroupBy('cars-table', 'Type')

// Enable grouping for the "Type" column
Reactable.toggleGroupBy('cars-table', 'Type', true)

// Disable grouping for the "Type" column
Reactable.toggleGroupBy('cars-table', 'Type', false)


Sets the groupBy columns for the table. To clear the groupBy columns, set columnIds to an empty array, [].

  tableId: string,
  columnIds: Array<string>


// Set the groupBy columns to "Type" and "Manufacturer"
Reactable.setGroupBy('cars-table', ['Type', 'Manufacturer'])

// Clear the groupBy columns
Reactable.setGroupBy('cars-table', [])


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.

  tableId: string,
  isExpanded?: boolean


// Toggle expanded state for all rows

// Expand all rows
Reactable.toggleAllRowsExpanded('cars-table', true)

// Collapse all rows
Reactable.toggleAllRowsExpanded('cars-table', false)


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.

  tableId: string,
  meta?: object | Function


// Set metadata, updating the values for the `count`, `enabled`, and `formatter` properties
Reactable.setMeta('cars-table', { count: 123, enabled: true, formatter: value => '$' + value })

// Set metadata using a function that increments `count` and toggles an `enabled` boolean
Reactable.setMeta('cars-table', prevMeta => {
  return { count: prevMeta.count + 1, enabled: !prevMeta.enabled }

// Clear metadata
Reactable.setMeta('cars-table', undefined)


Gets the current state of a table.

Reactable.getState(tableId: string)


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.3.0.9000)


// { page: 2, searchValue: 'petal', ... }