From 3199c2dad9c3f422b3418e59e1390ffe06472544 Mon Sep 17 00:00:00 2001 From: Pinkesh Date: Thu, 27 Aug 2026 10:44:20 +0530 Subject: [PATCH] Update DataTable Widget --- .../ui/widgets/built-in-widgets/datatable.md | 552 +++++------------- .../imgs/data-table-header.avif | Bin 87319 -> 13274 bytes .../imgs/paginated-data-table-fi.avif | Bin 149812 -> 25799 bytes 3 files changed, 154 insertions(+), 398 deletions(-) diff --git a/docs/resources/ui/widgets/built-in-widgets/datatable.md b/docs/resources/ui/widgets/built-in-widgets/datatable.md index 965eb95d..9d1aee96 100644 --- a/docs/resources/ui/widgets/built-in-widgets/datatable.md +++ b/docs/resources/ui/widgets/built-in-widgets/datatable.md @@ -2,73 +2,48 @@ slug: datatable title: DataTable tags: [Layout Elements] -description: Learn how to add DataTable widget in your FlutterFlow project. +description: Learn how to add, populate, sort, search, select, paginate, and style a DataTable widget in FlutterFlow. --- -# DataTable (Paginated) +# DataTable -The DataTable is a widget used to display data in a table format. It organizes information into rows and columns, similar to a spreadsheet, making it easier to read and understand large amounts of data. +The DataTable widget displays structured data in rows and columns. It is useful for presenting datasets such as employee directories, inventories, orders, and reports. -For example, you could use it to display a list of employees in a company, with each row representing an individual employee and the columns showing the employee's name, age, department, and salary. +The DataTable can be configured with pagination, sorting, searching, row selection, and horizontal scrolling for smaller screens. -Additionally, this widget supports pagination, which can handle large datasets by displaying them in manageable chunks. +![A paginated DataTable displaying employee records](imgs/paginated-data-table-fi.avif) -![paginated-data-table-fi](imgs/paginated-data-table-fi.avif) +## Adding the DataTable Widget -## Adding DataTable widget +1. Open the [Widget Palette](../../../../intro/ff-ui/widget-palette.md) and locate **DataTable** under **Layout Elements**. +2. Drag the widget onto the canvas or add it from the Widget Tree. +3. Configure the two predefined child widgets: + - **DataTableHeader** defines a column heading. Select its **Text** widget to change the heading. + - **DataTableCell** displays a value in each generated row. It contains a Text widget by default, but you can replace it with another widget. +4. To change the number of columns, select the DataTable and set **Paginated Data Table Properties > Number of Columns**. -Let's see how to add a DataTable widget by building an example that shows a list of all employees in a company. Here's how it looks: +![DataTableHeader and DataTableCell widgets identified with arrows](imgs/data-table-header.avif) -
- -
-

+### Populating the DataTable with Data + +The following example displays employee records retrieved from Firestore: + +1. Retrieve the records by adding a [Query Collection](../../../../resources/control-flow/backend-logic/backend-query/query-collection.md) to a parent widget, such as the Page or Column. Alternatively, run a **Query Collection** action when the page loads and store its result in [page state](../../../../resources/ui/pages/page-lifecycle.md#page-state). +2. Select the DataTable and [generate dynamic children](../composing-widgets/generate-dynamic-children.md) from the retrieved list. +3. Select each **DataTableCell > Text** widget and bind it to the appropriate field in the current record. -The steps to add DataTable and display the employees' details are: - -1. Open the [Widget Palette](../../../../intro/ff-ui/widget-palette.md) and locate the **DataTable** widget under the **Layout Elements** tab. You can drag it into your desired location or add it directly from the widget tree or canvas area. -2. It adds two types of predefined widgets: - 1. **DataTableHeader**: This refers to the top row of the table, which displays the names of the columns. To change its text, click on the **DataTableHeader > Text** widget, move to the properties panel and give it a name. - 2. **DataTableCell**: This displays the actual data. By default, it comes with the Text widget. However, you can replace it with any other widget based on your requirements. - ![data-table-header](imgs/data-table-header.avif) - -3. By default, it shows three columns. To show more, select the **DataTable** widget, move to the **properties panel > Paginated Data Table Properties >** enter the **Number of Columns** you want. -4. For the demonstration purpose, let's display data from Firestore: - 1. First, ensure you have created a collection. - 2. *It's **important to note** that, unlike other widgets, you cannot directly have a backend query on the DataTable widget. Because if you do so, you won't have access to the query result (list of employees) for further use, such as sorting and searching. Hence, getting the backend query result on a parent widget and then using that result to populate DataTable is advisable.* - 3. For this example, on page load, we'll add a Query Collection action and save the result in a page state variable. - 4. On the **DataTable** widget, generate dynamic children using the page state variable (which holds a list of employees). - 5. Display data in the **DataTableCell > Text**. +:::info +Retrieve the data from a parent widget or an action instead of querying directly on the DataTable. This keeps the complete list available for operations such as sorting, searching, and row selection. See [**Backend Query**](../../../../resources/control-flow/backend-logic/backend-query/backend-query.md) for more information. +:::
- -
-

+Enable row selection when users need to perform an action on one or more records, such as editing, deleting, or exporting them. -To enable sorting: +1. Create a [page state](../../../../resources/ui/pages/page-lifecycle.md#creating-a-page-state) variable that stores a list of the selected records. +2. Select the DataTable and enable **Paginated Data Table Properties > Selectable**. +3. On the button that processes the selection, add an [Update Page State](../../../../resources/ui/pages/page-lifecycle.md#update-page-state-action) action. +4. Get the selected indices from **Widget State > DataTable Selected Rows**. Pass them and the list currently generating the DataTable rows to a [custom function](../../../../ff-concepts/adding-customization/custom-functions.md). If the table is filtered or sorted, use that filtered or sorted list rather than the original list. -1. Select the **DataTableHeader**, move to the **Properties Panel**, and turn on the **Sortable** toggle. Apply this to each column you want to sort -2. Select the DataTable widget, select **Actions** from the Properties panel, and open **Action Flow Editor**. -3. Select the **On Sort Changed**. Actions added under this will be triggered whenever the user clicks on any column header that has sorting enabled. -4. For this example, we update the same page state variable (that populates the DataTable) with the sorted data using the following custom function. +For example, the following function returns the employee records at the selected indices: - -```dart -List sortMyData( - List listToSort, - bool isAsc, - int sortColumIndex, +```jsx +List getSelectedEmployees( + List employees, + List selectedIndices, ) { /// MODIFY CODE ONLY BELOW THIS LINE - // Sort by 'name' for 0, 'age' for 1, 'position' for 2 in code. - switch (sortColumIndex) { - case 0: - listToSort.sort((a, b) => a.name.compareTo(b.name)); - break; - case 1: - listToSort.sort((a, b) => a.age.compareTo(b.age)); - break; - case 2: - listToSort.sort((a, b) => a.position.compareTo(b.position)); - break; - default: - break; - } - if (!isAsc) { - listToSort = listToSort.reversed.toList(); - } - return listToSort; + return selectedIndices + .where((index) => index >= 0 && index < employees.length) + .map((index) => employees[index]) + .toList(); /// MODIFY CODE ONLY ABOVE THIS LINE } ``` -
- -
-

- -## Searching +## Handling DataTable Events -You can add search functionality to the DataTable widget using our Simple Search feature. However, for this specific widget, instead of using a [Conditional Builder](../../../../ff-concepts/layout/responsive-widgets/conditional-builder-widget.md) widget, you can directly utilize the [Conditional Value](../../../../resources/control-flow/functions/conditional-logic.md#conditional-value-ifthenelse) to determine which result to display based on the `IsShowFullList` variable. +Add actions to DataTable events from the **Actions** tab in the Properties Panel. -![searching-through-table](imgs/searching-through-table.avif) +### On Sort Changed -## Selecting rows +**On Sort Changed** runs when a user selects a column header that has sorting enabled. It provides: -You might want to allow users to select one or more of its rows for tasks like editing, deleting, or performing specific actions on the selected data. For example, preparing a list of promoted employees from the main employee listing. - -
- -
-

+- **Sorted Column Index**: The zero-based index of the selected column. For example, `0` represents the first column. +- **Is Ascending**: Whether the selected sort direction is ascending. -To achieve this, create a page state variable to store the selected list. Upon button click, update this variable with the chosen selections from the DataTable. **Note that** the DataTable provides a list of selected row indices; you'll need a [custom function](../../../../ff-concepts/adding-customization/cloud-functions.md) to retrieve the actual rows corresponding to these indices. +To add sorting: -Here are the exact steps: +1. Select each **DataTableHeader** that users can sort and enable **Sortable**. +2. Select the DataTable and add an action under **On Sort Changed**. +3. Pass **Sorted Column Index**, **Is Ascending**, and the list currently generating the DataTable rows to a custom function. +4. Update the page state variable that generates the DataTable rows with the function result. -1. First, create a [page state](../../../../resources/ui/pages/page-lifecycle.md#creating-a-page-state) variable that will hold the list of selected rows. -2. Select the **DataTable**, move to the **Properties Panel > Paginated Data Table Properties >** turn on the **Selectable** toggle. -3. On button click, [update the page state](../../../../resources/ui/pages/page-lifecycle.md#update-page-state-action) variable with the selected rows. While adding this action, use the following custom function to retrieve the selected items based on the indices. You can get the list of selected rows indices via **Widget State > DataTable Selected Rows**. -4. Optionally, you could pass this variable to a new page to display the selection. +:::info +The DataTable reports the selected column and direction but does not sort the records automatically. Your action must update the list used to generate the rows. +::: -Custom function: +The following example sorts a copy of the employee list without modifying the input list: -```dart -List findPromotedEmps( - List allEmps, - List selecteEmpsIndex, +```jsx +List sortEmployees( + List employees, + bool isAscending, + int sortColumnIndex, ) { - // MODIFY CODE ONLY BELOW THIS LINE - // return allEmps based on selecteEmpsIndex - List promotedEmps = []; - for (int i = 0; i < selecteEmpsIndex.length; i++) { - int index = selecteEmpsIndex[i]; - if (index >= 0 && index < allEmps.length) { - EmployeesRecord emp = allEmps[index]; - promotedEmps.add(emp); - } - } - return promotedEmps; - /// MODIFY CODE ONLY ABOVE THIS LINE - } -``` - -
- -
-

- -## Get notified on page changed - -You might want to get a callback whenever a user taps on the next page of the DataTable. For example, to make an API call to retrieve the data for the next page. - -
- -
-

- -To do so: + /// MODIFY CODE ONLY BELOW THIS LINE -1. Select the **DataTable** widget. -2. Select **Actions** from the Properties panel and open **Action Flow Editor**. -3. Select **On Page Changed**. This callback gives you the **Current Row Index**, which is the index of the first row of a new page. For example, if you have 25 items (0-24) on the current page, the **Current Row Index** value will be 25. This is helpful in APIs that fetch a fixed set of data by specifying a starting position ([offset](https://developer.box.com/guides/api-calls/pagination/offset-based/)). -4. Now, add an action to call the paginated API (that returns the result in chunks). See [how to add the paginated API](../../../../resources/control-flow/backend-logic/api/rest-api.md#query-parameters) call by adding query parameters. For this example, we use this API: https://reqres.in/api/users?per_page=7&page=1. **Note**: this API uses page-based rather than offset-based pagination, requiring manual adjustment of the page variable. -5. On the success of the API call, you can add an action to append the new data in the current list. For this, you can add the following custom function to add new results to existing data. + final sortedEmployees = List.from(employees); -```dart -List addAlldatatoList( - List currentUsersList, - List newUsersList, -) { - /// MODIFY CODE ONLY BELOW THIS LINE + switch (sortColumnIndex) { + case 0: + sortedEmployees.sort((a, b) => a.name.compareTo(b.name)); + break; + case 1: + sortedEmployees.sort((a, b) => a.age.compareTo(b.age)); + break; + case 2: + sortedEmployees.sort((a, b) => a.position.compareTo(b.position)); + break; + } - // add all newUsersList to currentUsersList - currentUsersList.addAll(newUsersList); - return currentUsersList; + return isAscending + ? sortedEmployees + : sortedEmployees.reversed.toList(); /// MODIFY CODE ONLY ABOVE THIS LINE } @@ -339,12 +165,12 @@ List addAlldatatoList(
- -
-

+For an API-backed DataTable: +1. Select the DataTable and add an action under **On Rows Per Page Changed**. +2. Use the event's rows-per-page value to update the API's `limit` or the corresponding page state variable. +3. Reset the stored pagination offset to `0`. +4. Call the API again and update the list displayed by the DataTable. -:::info -Typically, setting the size explicitly isn't necessary for a DataTable, as it's designed to showcase large datasets and should utilize all available space. However, to enable horizontal scrolling in the DataTable (when content exceeds screen width), you must specify the **Min Width**. -::: +## Customizing the DataTable -
- -
-

+Select the DataTable and use the Properties Panel to configure the following options. -### Adjust row and column spacing +### Paginated Data Table Properties -To modify the row and column spacing, move to the **Properties Panel > Layout Properties** and then tweak the following properties: +- **Number of Columns** sets the number of columns in the table. +- **Number of Rows (Optional)** sets the total number of rows in the DataTable. Leave it unset to use the number of generated rows. +- **UI Builder Number of Rows (Optional)** sets how many sample rows appear on the canvas while designing the page. It does not limit the rows displayed in the running app. +- **Paginated** displays the rows across multiple pages. Disable it to use a regular DataTable without pagination. + - **Hide Paginator** hides the pagination controls. + - **Show First And Last Buttons** adds shortcuts to the first and last pages. +- **Selectable** allows users to select one or more rows. + - **Rebuild Page on Select** appears when **Selectable** is enabled. Enable it to rebuild the page whenever the row selection changes, allowing other widgets that depend on the selection to update immediately. -- **Header Row Height**: This changes the height of the header. -- **Data Row Height**: This changes the height of all the rows. -- **Column Spacing**: This changes the distance between columns. +### Layout Properties -
- -
-

+- **Table Width** and **Table Height** control the overall table dimensions. You can set these values in pixels or as percentages. +- **Header Row Height** controls the height of the column-header row. +- **Data Row Height** controls the height of each data row. +- **Column Spacing** controls the horizontal space between columns. -### Customize DataTable color +### Setting a Minimum Width -To modify the DataTable color, navigate to the **Properties Panel > Style Properties**, where you can set colors for various elements: +Under **Layout Properties**, set **Min Width** to define the minimum width of the DataTable. You can enter the value in pixels or as a percentage. -- **Header Row Color**: This changes the background color of the header row. -- **Row Color**: This sets the background color for all rows. -- **Alternate Row Color**: This allows for a different background color for alternate rows. -- **Sort Icon Color**: This alters the color of the sort icon used in sortable columns. +If the DataTable's minimum width exceeds the available screen width, the table becomes horizontally scrollable. This prevents column content from being compressed or wrapped excessively on smaller screens.
Style Proper height: 0, width: '100%'}}>