Skip to main content

Build custom views using repeatable components

Learn how to display and interact with your data using list views.

List View components are a common way to display and interact with your data. You nest components within the list view and configure them to display certain values. You only have to do this once because the list view repeats the configuration for every entry in your data source. See the demo below for an example.

Demo

In the demo, the underlying configuration for displaying user names, emails, etc. is only done once. The configuration is then repeated for every user in the data source resulting in the grid-like view.

Add the component and specify the data

Add a List View component to the canvas and select a Data source. You can write JavaScript, pass an array, or use query data as your data source. The only requirement is that the data source is an array (primitive and object arrays both work).

Retool tries to set a primary key for List View components when you select a data source. If your app has multiple user input components, make sure the primary key is set correctly. This ensures your app state is correct after users make changes like adding or sorting data.

After selecting a data source, Retool seeds the component with containers for each item in your data source. You add components to the first container and they're automatically propagated to the other containers. Retool sets some default values, but you use the item and i variables to display data in each component.

The item variable

The item variable corresponds to the value of an entry in your data source. It's equivalent to referencing listView1.data[i]. You can use item to access values in your data source, such as {{ item.id }} or {{ item.value }}.

The i variable

The i variable is a number that represents the index of an entry in your data source. Since a list view is a repeatable component, each repeated instance has a different index which you can use to render and access unique values.

i is often used to iterate over a set of values and perform some kind of action. For example, you could iterate over an entire list view to update values, make API requests, send emails, etc. For example, this JavaScript transformer iterates over all the entries in listView1, and returns each sales person with over 200 sales.

var salesPerson = {{ listView1.data }};
var highSales = salesPerson.filter(i => i.sales > 200);
return highSales;

Reference nested components

You can reference nested components from other nested components within the same list view instance (e.g., {{ componentName.value }}). Nested components cannot be referenced outside of List View. If you need to reference the source data of a list item, you can reference the data or instanceValues of List View.

Aggregate nested form components

If you need to access the value of an input component within List View, toggle Enable instance values on. When enabled, List View attempts to evaluate all input values and make them available in the instanceValues property.

instanceValues is an array of objects for every instance of the list view, where each object is a mapping of an input's formDataKey to its value. This also includes the primaryKey of the list item.

For example, you can use a JavaScript transformer to iterate over a list of Number Input components and return the sum total:

Reference instance values
const formData = {{ listViewName.instanceValues }}
const sum = formData.reduce((sum, data) => sum += data.numberInput1, 0)
return sum

Use resetInstanceValues() or clearInstanceValues() to reset or clear input values for a List View anywhere in the app.

Customize appearance

You can customize the overall appearance of the List View component. Select the component and modify appearance settings like height, layout type, etc.

Retool recommends using a fixed height for List Views. If needed, you can use auto heights with server side pagination but it requires additional configuration.

Auto height configuration

You might use auto height when your data set is less than 25 items, or when fixed heights don't otherwise fit your use case. For the latter, Retool recommends using the auto height setting with server side pagination. This requires some additional code to function.

For example, you can use a JavaScript transformer and a Page Input component to return only a subset of values from your data source.

const currentPage = {{ pageInput1.value }} - 1
const pageSize = 5
const pageStart = currentPage * pageSize
const pageEnd = pageStart + pageSize

return {{filteredTableData.value}}.slice(pageStart, pageEnd)

After you set the List View's data source to the transformer value, you add a Page Input component. Page Input components include a Page count value that you can set manually, or you can write JavaScript to display the page count dynamically. For example, {{Math.ceil(filteredTableData.value.length / 5)}} divides the number of items returned to calculate the page count where each page contains five items. See the demo below for a walkthrough.

Nest List View within List View

You can nest a List View component within another List View component. This nesting dynamically generates UI elements based on multidimensional arrays and tree-like data structures—for example, org charts or threaded comments. Nested List Views support up to three levels of depth and can also reference nested components using componentName.value.

The following demo app uses two List View components. The first contains the teams: Engineering, Marketing, and Sales. The second is nested inside the first and contains the team members.

Demo

The transformedJS and transformedSql queries convert sampleData into an object you can use in a nested List View.

sampleData
return {
name: ["Bob", "Kate", "Sarah", "Ali", "Joe", "Lisa", "Lenny"],
team: [
"Engineering",
"Engineering",
"Marketing",
"Sales",
"Engineering",
"Sales",
"Marketing",
],
};

To configure the demo app, the first List View component uses the transformedDataJs query as its data source. Then, {{ item.team }} is used to display the team names. The second List View's data source is set to {{ item.members }}, and {{ item } displays the members of each team. Click through the demo to view the configuration.