Build tables
Learn how to display and interact with data using the Table component.
Updated Table component
This guide uses the legacy Table component. See the updated version of this guide for using the updated Table component.
Tables are a common way to view and interact with your data. You can sort, filter, paginate, and download rows of information. Tables also support row selection and insertion, server-side pagination, and custom columns.
Demo
Try out the app to see tables in action (edits are disabled). The table incorporates different column types, and dynamically highlights cells in the Sales column if the value is lower than 200.
Load data in a table
When you drag a Table component to the Canvas, it automatically displays data from one of your queries. If you don't have any queries, Retool initially populates the table with test data in JSON format. You can change the data displayed in a table by editing the Data property. Use the queryName.data
format to choose the query.
Change column types
When you add tables to the Canvas, their columns are set to Auto. You can set column types manually by clicking on the column in the Inspect tab and selecting the type from the Column type dropdown. You can also manage column types dynamically with the Use dynamic column settings option.
Editable table columns
After populating a table with data, you can edit cells and add rows with some additional configuration. To make a column editable, select a table to open the Inspect tab in the right panel. Scroll to the Columns section and select the boxes next to the columns you want to make editable.
After making columns editable, you can double click on a cell to edit it. When you edit cells, changes are saved in the table's recordUpdates
property. This tracks the changes you've made but it doesn't update the underlying data source that your query connects to. To save edits back to your data source, you must write an appropriate query to update your data. For example, saving changes to a PostgreSQL database can be done using a Bulk update query.
After creating the bulk update query, you need to connect it to the table. Open the Inspect tab again for the table and scroll to the Event handlers section. Add a Save changes event handler that runs the bulk update query.
Add new data to tables
You can add rows to tables and save the changes as new data. This allows users to add data without needing to build a separate group of inputs.
In the Inspect tab, you can enable the Show add row button option which adds a + button to your table. This allows users to add rows. Similar to editing cells, you need to create a query that updates your data source and an event handler to trigger the query when a row is added.
Columns also need to be editable to add rows.
To write back to your data source, write an insert query using the GUI editor.
After creating the insert query, you need to connect it to the table. Open the Inspect tab again for the table and scroll to the Event handlers section. Add a Save new event handler that runs the insert query.
Dynamic values in new rows
You can use dynamic values if you have columns you don't want users to edit, or if you want to automate some of the values added in a new row. These values are generated when the row is added, and don't require manual input from the user. For example, if your table has a timestamp column, you can use {{ moment() }}
to generate the timestamp when the query runs.
Automatically reload table data
By default, tables include a refresh button that reloads its query. When users click the button, the query runs and the table updates to reflect the latest data. If you want to automatically reload table data when changes are saved, add an event handler to the query that updates your data source. Configure the event handler so that when the query succeeds, it runs the query that populates your table.
Custom columns
You can add custom columns to tables using the + Add button in the Inspect tab. Custom columns are often used to calculate data based on other values in your Retool app. For example, if you have a monthlyIncome
column and you want to calculate a yearlyIncome
column, you could use {{ currentRow.monthlyIncome * 12 }}
Custom columns have the same attributes that regular table columns have including:
- Column types
- Custom titles
- Background color
- HTML, overflow, sorting, and dynamic visibility
You can rename custom columns but each column still has a key
that you can't edit. If you want to access the column mapper dynamically, you need to use the key
, not the column name.
Accessing custom column data in other components
Custom column data isn't accessible in
{{ table1.data }}
or other properties of the table object. If you want to access custom column values in other components (e.g., using{{ table1.selectedRow.data.custom_column }}
, use a Query Transformer to calculate the additional values, which then propagates to your table.
Sort, filter, and customize data presentation
Tables come with prebuilt functionality for sorting and filtering data. You can click on a column to sort it, and there's a filter button in the lower right corner of the table that allows you to create custom filters. You can combine a table with a Text Input component to create a search field that serves as another way of filtering data.
Table filters on custom columns aren't currently supported.
Show and hide columns
When you click a column in the Inspect tab, there's a Show column toggle that you can switch on and off. You can also use dynamic column settings to hide columns.
Pagination
In the Inspect tab, you can choose between Pagination and Scroll options for handling overflow items.
You can also enable server-side pagination. You write queries that include parameters to define a subset of data to retrieve, server-side. This is recommended when working with large datasets to reduce the amount of data your table uses at a time, which can help your app's performance.
Sorting of tables using server-side pagination must be done on the server. You can write queries that use the table's sortedColumn
and sortedDesc
properties to achieve this.
Dynamic column settings
You can enable dynamic column settings by toggling the Use dynamic column settings on in the Inspect tab. This setting gives you additional control over table columns, including which columns are shown, how they're styled, etc.
When you enable dynamic column settings, a Column settings property is displayed. This property supports an array of strings (column keys) or objects, each overriding the settings for one column.
Enabling the Apply to column order option overrides the current column order with the order passed in the Column settings property. If there isn't an object with a name key that matches a column, that column is hidden. These are the properties that you can override with dynamic column settings.
Certain settings are only evaluated when data changes. You must reload the table data when setting these values for changes to be reflected. Click the Reload button on the table if you've enabled it, rerun the query that is used by the table, or select Reset app state from the •••
App settings menu in the toolbar.
Property | Description | Evaluated when data changes |
---|---|---|
type | Set the column type. Accepts all types except for dropdown . | No |
frozen | Freezes a column. Accepts left and right . | No |
mapper | Sets the mapped value for a column. Supports JavaScript expressions with escaped brackets (e.g., {\{ self * 2 }\} . | Yes |
colorMapper | Sets the mapped value for the column's color. Supports JavaScript expressions with escaped brackets (e.g., "colorMapper":'{\{Math.abs(i % 2) == 1?"grey":"blue"}\}' ). | Yes |
restrictedEditingMapper | Boolean value that restricts the editing of cell values within an editable column. If true , cell values cannot be edited. Supports JavaScript expressions with escaped brackets. | Yes |
modalId | Opens the modal of another modal column. If the key is invalid, a modal with that key still opens. | Yes |
Dynamic column types
These are the supported dynamic column type
values.
boolean
currency
date
dateTime
html
imageUpload
imageUrl
json
link
markdown
modal
multilineText
number
percent
rating
tag
tags
text
time
userEmail
Hide columns
You define the columns to show by passing in an array of objects that map to the columns. If there isn't an object with a name key that matches a column, that column is hidden.
Set column mappers
Column mappers allow you to change default column values. You can set them using the Mapped value on each column or with dynamic column settings. With dynamic column settings, you can use a string inside of the object for each column to map values, but you need to escape the {{ }}
tag. For example, { "name": "email", "type":"default", "mapper":'{\{self+1}\}'}
uses the current cell value (self
) and adds 1
to it.
Dynamically created mappers only update when the table data or app loads, so if you edit the mapper value, you need to reload the data.
After setting a dynamic mapper, the Mapped value field on the column settings is greyed out and the value updates in realtime.
Set column background color
You can set background colors using the Styles section of the Inspect tab or with the colorMapper
key. When you set the colorMapper
key, alternate single or double quotes so that the outer quotes are not repeated inside the string. For example, "colorMapper":'{\{Math.abs(i % 2) == 1?"#D1D1D1":"#3C92DC"}\}'
.
Common table variables
currentRow
, currentColumn
, self
, and i
are commonly used with tables. self
and i
work with other components, but they have unique meanings when used with table column settings. With tables, i
is the index of the current row in the original dataset, and self
is the value of the current cell.
Variables like currentRow
and self
are useful in situations where you want to access values in a table and then calculate a new value. For example, {{ self * 10 }}
takes the current cell and multiplies it by ten. You can also do something like {{self + ' ' + '(Last sale: + currentRow.last_sale)'}}
to combine two values and map them to a column.
i
is often used to iterate over a set of values and perform some kind of action. For example, you can iterate over each row in a table and update values, make API requests, send emails, etc. For example, this JavaScript transformer iterates over all rows in table1
, and returns each sales person with over 200 sales.
var salesPerson = {{ table1.data }};
var highSales = salesPerson.filter(i => i.sales > 200);
return highSales;
See the Table component reference documentation for more information on properties, events, and JavaScript methods that you can use with tables.
Updated 3 days ago