From f84e9c3c45c3856afbac20007f3e2cb56858dda3 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Tue, 7 Jul 2026 12:05:44 +0530 Subject: [PATCH 01/18] FLUT-1038842-[others][flutter]: Direct AI changes --- Flutter/datagrid/accessibility.md | 158 +++- Flutter/datagrid/column-drag-and-drop.md | 359 ++++--- Flutter/datagrid/column-types.md | 60 +- Flutter/datagrid/columns-resizing.md | 41 +- Flutter/datagrid/columns-sizing.md | 282 ++++-- Flutter/datagrid/conditional-styling.md | 39 +- Flutter/datagrid/data-binding.md | 362 ++++--- Flutter/datagrid/editing.md | 98 +- Flutter/datagrid/export-to-excel.md | 184 ++-- Flutter/datagrid/export-to-pdf.md | 221 +++-- Flutter/datagrid/filtering.md | 307 +++--- Flutter/datagrid/footer.md | 80 +- Flutter/datagrid/freeze-panes.md | 79 +- Flutter/datagrid/getting-started.md | 287 +++--- Flutter/datagrid/grouping.md | 207 +++- .../how-to/custom-widget-on-flutterflow.md | 54 +- Flutter/datagrid/load-more.md | 219 ++++- Flutter/datagrid/localization.md | 427 +++++---- Flutter/datagrid/overview.md | 71 +- Flutter/datagrid/paging.md | 182 ++-- Flutter/datagrid/placeholder.md | 31 +- Flutter/datagrid/pull-to-refresh.md | 158 +++- Flutter/datagrid/right-to-left.md | 112 ++- Flutter/datagrid/row-height-customization.md | 93 +- Flutter/datagrid/scrolling.md | 92 +- Flutter/datagrid/selection.md | 160 +++- Flutter/datagrid/sorting.md | 280 +++--- Flutter/datagrid/stacked-headers.md | 162 +++- Flutter/datagrid/styles.md | 40 +- Flutter/datagrid/summaries.md | 892 +++++++----------- Flutter/datagrid/swiping.md | 177 +++- 31 files changed, 3722 insertions(+), 2192 deletions(-) diff --git a/Flutter/datagrid/accessibility.md b/Flutter/datagrid/accessibility.md index 7ce867128..f5835ad5e 100644 --- a/Flutter/datagrid/accessibility.md +++ b/Flutter/datagrid/accessibility.md @@ -9,9 +9,17 @@ documentation: ug # Accessibility in Flutter DataGrid (SfDataGrid) +The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget is designed with comprehensive accessibility features to ensure all users, including those using assistive technologies, can interact with data effectively. This section covers built-in accessibility support and best practices for implementing an accessible data grid experience. + +> **Note:** SfDataGrid accessibility features are supported on Android, iOS, and web platforms. Ensure your application targets Flutter 3.0 or higher and syncfusion_flutter_datagrid 20.1.0 or above. + ## Screen reader support -The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) can be accessed easily by screen readers in the following ways on Android and iOS platforms: +The SfDataGrid supports screen readers through the following interactions on Android and iOS platforms: + +* Cell contents can be read by tapping the required cell. +* Adjacent cell content can be navigated by swiping left or right. +* Scroll the DataGrid vertically and horizontally by dragging with two fingers. * Cell contents can be read by tapping the required cell. * Read adjacent cell content by swiping right or left. @@ -19,24 +27,27 @@ The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/lates ## Sufficient contrast -The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides sufficient color contrast to make cell content more readable. Use the following properties to customize the appearance of the DataGrid elements: +The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides sufficient color contrast to make cell content more readable and compliant with WCAG 2.1 AA standards. Customize the appearance of DataGrid elements using the following properties: -* [currentCellStyle](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCurrentCellStyle-class.html) -* [frozenPaneElevation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneElevation.html) -* [frozenPaneLineColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneLineColor.html) -* [gridLineColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/gridLineColor.html) -* [headerColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerColor.html) -* [headerHoverColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerHoverColor.html) -* [selectionColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionColor.html) -* [sortIconColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/sortIconColor.html) +* [`currentCellStyle`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCurrentCellStyle-class.html) — Styling for the currently selected cell +* [`frozenPaneElevation`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneElevation.html) — Shadow depth for frozen panes +* [`frozenPaneLineColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneLineColor.html) — Border color for frozen pane dividers +* [`gridLineColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/gridLineColor.html) — Color of grid lines between cells +* [`headerColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerColor.html) — Background color of column headers +* [`headerHoverColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerHoverColor.html) — Header background color on hover +* [`selectionColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionColor.html) — Background color for selected cells +* [`sortIconColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/sortIconColor.html) — Color of sort indicator icons ## Large fonts -Since [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) receives widgets from the user for each cell, the font size in those widgets will automatically adjust based on OS settings in Android and iOS platforms. To ensure cell content remains clearly visible, the row heights in the DataGrid will automatically adjust based on the `MediaQueryData.textScaleFactor`. +Since [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) receives widgets from the user for each cell, the font size in those widgets automatically adjusts based on OS text scale settings on Android and iOS platforms. To ensure cell content remains clearly visible, row heights adjust automatically based on the [`MediaQueryData.textScaleFactor`](https://api.flutter.dev/flutter/widgets/MediaQueryData/textScaleFactor.html). + +The following example demonstrates how to apply a custom text scale factor: {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override @@ -54,8 +65,8 @@ Widget build(BuildContext context) { child: Text( 'ID', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'name', @@ -65,8 +76,8 @@ Widget build(BuildContext context) { child: Text( 'Name', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'salary', @@ -76,8 +87,8 @@ Widget build(BuildContext context) { child: Text( 'Salary', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'designation', @@ -87,11 +98,11 @@ Widget build(BuildContext context) { child: Text( 'Designation', overflow: TextOverflow.ellipsis, - ) - ) - ) - ] - ) + ), + ), + ), + ], + ), ); } @@ -100,11 +111,67 @@ Widget build(BuildContext context) { ## Keyboard navigation -The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides keyboard navigation support when the [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) and [navigationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) are enabled. Refer to this [link](https://help.syncfusion.com/flutter/datagrid/selection#keyboard-behavior) for supported keys and their purpose. +The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) supports keyboard navigation for enhanced accessibility and desktop usability. Enable keyboard navigation by configuring the [`selectionMode`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) and [`navigationMode`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) properties. + +**Supported keyboard interactions:** +* **Arrow keys** — Navigate between cells (up, down, left, right) +* **Tab/Shift+Tab** — Move focus to the next/previous cell +* **Enter** — Select/activate the current cell +* **Ctrl+Home** — Navigate to the first cell +* **Ctrl+End** — Navigate to the last cell +* **Page Up/Page Down** — Scroll vertically by one page + +For detailed keyboard behavior documentation, refer to the [keyboard behavior guide](https://help.syncfusion.com/flutter/datagrid/selection#keyboard-behavior). + +The following example enables keyboard navigation: + +{% tabs %} +{% highlight Dart %} + +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + +@override +Widget build(BuildContext context) { + return SfDataGrid( + source: _employeeDataSource, + selectionMode: GridSelectionMode.single, + navigationMode: GridNavigationMode.cell, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary'), + ), + ), + ], + ); +} + +{% endhighlight %} +{% endtabs %} ## Visual density -The row heights in [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) will automatically adjust based on the [visualDensity](https://api.flutter.dev/flutter/material/ThemeData/visualDensity.html) property. +Row heights in [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) automatically adjust based on the [`visualDensity`](https://api.flutter.dev/flutter/material/ThemeData/visualDensity.html) property. This allows you to create compact or spacious layouts that adapt to user preferences and device capabilities. {% tabs %} {% highlight Dart %} @@ -117,7 +184,7 @@ Widget build(BuildContext context) { return Theme( data: ThemeData(visualDensity: VisualDensity.compact), child: SfDataGrid( - source: _employeeDataSource, + source: _employeeDataSource, columns: [ GridColumn( columnName: 'id', @@ -127,8 +194,8 @@ Widget build(BuildContext context) { child: Text( 'ID', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'name', @@ -138,8 +205,8 @@ Widget build(BuildContext context) { child: Text( 'Name', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'salary', @@ -149,8 +216,8 @@ Widget build(BuildContext context) { child: Text( 'Salary', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'designation', @@ -160,14 +227,33 @@ Widget build(BuildContext context) { child: Text( 'Designation', overflow: TextOverflow.ellipsis, - ) - ) - ) - ] - ) + ), + ), + ), + ], + ), ); } {% endhighlight %} {% endtabs %} +## Testing accessibility + +To ensure your DataGrid implementation is accessible, follow these testing practices: + +* **Screen reader testing:** Use Android TalkBack or iOS VoiceOver to verify that cell content is properly announced. +* **Keyboard navigation:** Test all keyboard interactions on desktop platforms (Windows, macOS, Linux) to ensure proper navigation flow. +* **Color contrast:** Validate that all text meets WCAG 2.1 AA color contrast requirements (4.5:1 for normal text). +* **Text scaling:** Test your grid with text scale factors of 1.0x, 1.25x, 1.5x, and 2.0x to ensure content remains readable. +* **Automated testing:** Use accessibility scanning tools available in Android Studio and Xcode to detect potential accessibility issues. + +## Related resources + +For comprehensive information on implementing accessible DataGrid functionality, refer to the following resources: + +* [DataGrid selection guide](https://help.syncfusion.com/flutter/datagrid/selection) +* [DataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/) +* [Flutter accessibility guide](https://flutter.dev/docs/development/accessibility-and-localization/accessibility) +* [WCAG 2.1 accessibility standards](https://www.w3.org/WAI/WCAG21/quickref/) + diff --git a/Flutter/datagrid/column-drag-and-drop.md b/Flutter/datagrid/column-drag-and-drop.md index b0fc87c5b..66de86159 100644 --- a/Flutter/datagrid/column-drag-and-drop.md +++ b/Flutter/datagrid/column-drag-and-drop.md @@ -9,43 +9,113 @@ documentation: ug # Column drag and drop in Flutter DataGrid (SfDataGrid) -The SfDataGrid allows column header dragging and dropping by setting the [SfDataGrid.allowColumnsDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowColumnsDragging.html) property to `true` and returning `true` from the [SfDataGrid.onColumnDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnDragging.html) callback. During the column-dragging process, a drag feedback widget is displayed. By utilizing the `SfDataGrid.onColumnDragging` event, you can handle drag and drop operations according to your requirements. +The SfDataGrid enables columns to be dragged and dropped by setting the [SfDataGrid.allowColumnsDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowColumnsDragging.html) property to `true` and returning `true` from the [SfDataGrid.onColumnDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnDragging.html) callback. During the column-dragging process, a drag feedback widget is displayed. By utilizing the `SfDataGrid.onColumnDragging` callback, you can handle drag and drop operations to reorder columns dynamically. -The DataGrid provides the rearranged index of the dragged column, indicating its new position after being dropped. Inside the `onColumnDragging` callback, you can utilize this index to reorder the columns according to the desired position. This allows you to handle the column reordering directly within the callback at the sample level. +The DataGrid provides the rearranged index of the dragged column, indicating its new position after being dropped. Inside the `onColumnDragging` callback, you can utilize this index to reorder the columns to the desired position. This allows you to handle the column reordering directly within the callback at the sample level. + +## Prerequisites + +The following code example demonstrates the basic setup required for column drag and drop functionality: {% tabs %} -{% highlight Dart %} +{% highlight Dart %} - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.refreshDataGrid(); - } - return true; - }, - ), - ); +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + +class Employee { + Employee(this.id, this.name, this.designation, this.salary); + final int id; + final String name; + final String designation; + final double salary; + + dynamic operator [](String key) { + switch (key) { + case 'id': + return id; + case 'name': + return name; + case 'designation': + return designation; + case 'salary': + return salary; + default: + return ''; + } } +} + +{% endhighlight %} +{% endtabs %} + +## Enable column drag and drop + +The following code example shows how to enable column drag and drop functionality: + +{% tabs %} +{% highlight Dart %} + +late List columns; +late EmployeeDataSource employeeDataSource; + +@override +void initState() { + super.initState(); + List employees = [ + Employee(10001, 'James', 'Project Lead', 20000), + Employee(10002, 'Kathryn', 'Manager', 30000), + Employee(10003, 'Lara', 'Developer', 15000), + Employee(10004, 'Michael', 'Designer', 15000), + ]; + + columns = [ + GridColumn(columnName: 'id', label: const Center(child: Text('ID'))), + GridColumn(columnName: 'name', label: const Center(child: Text('Name'))), + GridColumn(columnName: 'designation', label: const Center(child: Text('Designation'))), + GridColumn(columnName: 'salary', label: const Center(child: Text('Salary'))), + ]; + + employeeDataSource = EmployeeDataSource(employees: employees, columns: columns); +} + +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ); +} class EmployeeDataSource extends DataGridSource { - EmployeeDataSource({required this.employees, required this.columns}) { + EmployeeDataSource({required List employees, required this.columns}) { + _employees = employees; buildDataGridRows(); } + late List _employees; + late List columns; + late List dataGridRows; + void buildDataGridRows() { - dataGridRows = employees.map((employee) { + dataGridRows = _employees.map((employee) { return DataGridRow( cells: columns.map((column) { return DataGridCell( @@ -56,17 +126,13 @@ class EmployeeDataSource extends DataGridSource { }).toList(); } - List employees = []; - List columns = []; - List dataGridRows = []; - @override List get rows => dataGridRows; @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { + cells: row.getCells().map((dataGridCell) { return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 8.0), @@ -75,10 +141,6 @@ class EmployeeDataSource extends DataGridSource { )); }).toList()); } - - refreshDataGrid() { - notifyListeners(); - } } {% endhighlight %} @@ -87,103 +149,109 @@ class EmployeeDataSource extends DataGridSource { Flutter datagrid shows a checkbox filter in web platform >**NOTE**: -* You can download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-column-drag-and-drop-in-flutter-datatable-sfdatagrid). -* To reorder the columns in the DataGrid, you should create an instance to hold the columns and then assign that instance to -the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) property instead of directly assigning the list of GridColumn. This allows you to reorder the collection within the callback, maintaining the desired column order. -* Additionally, it is important to build the rows based on the columns collection after reordering. This is necessary because -the column index may change after the columns have been rearranged. By rebuilding the rows based on the updated columns collection, you ensure that the row data aligns correctly with the reordered columns. +* To reorder the columns in the DataGrid, create an instance variable to hold the columns and then assign that instance to the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) property instead of directly assigning a list literal. This allows you to reorder the collection within the callback, maintaining the desired column order. +* After reordering columns, rebuild the rows based on the updated columns collection by calling `buildDataGridRows()` and `notifyListeners()`. This is necessary because the column index may change after reordering. By rebuilding the rows, you ensure that the row data aligns correctly with the reordered columns. +* Download the complete sample application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-column-drag-and-drop-in-flutter-datatable-sfdatagrid). ## onColumnDragging callback -The `SfDataGrid.onColumnDragging` callback is triggered when the column drags. This callback provides the following properties in the [DataGridColumnDragDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails-class.html). +The [SfDataGrid.onColumnDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnDragging.html) callback is triggered during column drag operations. This callback provides the following properties in the [DataGridColumnDragDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails-class.html): -* [from](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/from.html): Returns index of the currently dragging column. -* [to](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/to.html): Returns index of the column after being dropped. -* [action](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/action.html): Returns the column dragging details as the [DataGridColumnDragAction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragAction.html) enum. -* [offset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/offset.html): Returns the current offset of the dragging column. +* [from](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/from.html): The index of the currently dragging column. Use this to identify which column is being moved. +* [to](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/to.html): The index where the column will be dropped. This is null during drag updates and populated when the column is dropped. +* [action](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/action.html): Indicates the drag action as a [DataGridColumnDragAction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragAction.html) enum. The `update` action fires while dragging, and `dropped` fires when the column is released. +* [offset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridColumnDragDetails/offset.html): The current offset of the dragging column during the drag operation. Use this to calculate the drag position if needed. ## Cancel the column dropping for a specific column -You can cancel the column dropping at a specific column by returning `false` from the `SfDataGrid.onColumnDragging` callback. This allows you to restrict the column dropping for a specific column. +You can cancel the column dropping at a specific target column by returning `false` from the [SfDataGrid.onColumnDragging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnDragging.html) callback. This allows you to prevent columns from being dropped at certain positions or restrict specific columns from being dropped. + +In the following example, columns cannot be dropped at index 2 (the third column position): {% tabs %} {% highlight Dart %} - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.update && - details.to == 2) { - return false; - } - if (details.action == DataGridColumnDragAction.dropped && - details.to != null) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.refreshDataGrid(); - } - return true; - }, - ), - ); - } +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + // Prevent dropping at column index 2 + if (details.action == DataGridColumnDragAction.update && + details.to == 2) { + return false; + } + // Handle the drop action + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ); +} {% endhighlight %} {% endtabs %} ## Changing the feedback widget -The DataGrid allows you to change the drag feedback widget by returning a custom widget from the [SfDataGrid.columnDragFeedbackBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnDragFeedbackBuilder.html) builder. This allows you to change the drag feedback widget according to your requirements. +The DataGrid allows you to customize the feedback widget displayed during column dragging by using the [SfDataGrid.columnDragFeedbackBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnDragFeedbackBuilder.html) builder. This builder is called during drag operations and allows you to return a custom widget that represents the dragged column. {% tabs %} {% highlight Dart %} - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - columnDragFeedbackBuilder: (context, column) { - return Container( - height: 50, - width: column.actualWidth, - color: Colors.grey, - child: const Center( - child: DefaultTextStyle( - style: TextStyle( - fontSize: 14, - color: Colors.pink, - fontWeight: FontWeight.bold), - child: Text('Drag View'), - ), +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + columnDragFeedbackBuilder: (BuildContext context, GridColumn column) { + return Container( + height: 50, + width: column.actualWidth, + color: Colors.grey, + child: const Center( + child: DefaultTextStyle( + style: TextStyle( + fontSize: 14, + color: Colors.pink, + fontWeight: FontWeight.bold), + child: Text('Drag View'), ), - ); - }, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.refreshDataGrid(); - } - return true; - }, - ), - ); - } + ), + ); + }, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ); +} {% endhighlight %} {% endtabs %} @@ -192,50 +260,49 @@ The DataGrid allows you to change the drag feedback widget by returning a custom ## Drag indicator customization -The color and thickness of the drag indicator can be customized by the [SfDataGridThemeData.columnDragIndicatorColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorColor.html) and [SfDataGridThemeData.columnDragIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorStrokeWidth.html) properties. +The color and thickness of the drag indicator displayed during column dragging can be customized using the [SfDataGridThemeData.columnDragIndicatorColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorColor.html) and [SfDataGridThemeData.columnDragIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorStrokeWidth.html) properties. These properties are available in the `syncfusion_flutter_core` package through the [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html) widget. -The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the `syncfusion_flutter_core` package. So, import the following file. +>**NOTE**: +* The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the `syncfusion_flutter_core` package. +* Import the theme package: `import 'package:syncfusion_flutter_core/theme.dart';` + +The following code demonstrates how to customize the drag indicator appearance: {% tabs %} {% highlight Dart %} import 'package:syncfusion_flutter_core/theme.dart'; -{% endhighlight %} -{% endtabs %} - -The following code describes how to change the drag indicator color and thickness by using [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html). - -{% tabs %} -{% highlight Dart %} - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGridTheme( - data: SfDataGridThemeData( - columnDragIndicatorColor: Colors.pink, - columnDragIndicatorStrokeWidth: 3), - child: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.refreshDataGrid(); - } - return true; - }, - ), +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGridTheme( + data: SfDataGridThemeData( + columnDragIndicatorColor: Colors.pink, + columnDragIndicatorStrokeWidth: 3, ), - ); - } + child: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ), + ); +} {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/column-types.md b/Flutter/datagrid/column-types.md index 36cb0c9e4..9250fb582 100644 --- a/Flutter/datagrid/column-types.md +++ b/Flutter/datagrid/column-types.md @@ -9,7 +9,10 @@ documentation: ug # Column Types in Flutter DataGrid (SfDataGrid) -[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for loading any type of widget in each column. +[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for loading any type of widget in each column. The `SfDataGrid` supports two main column types: `GridColumn` for standard data binding and a `Checkbox` column for row selection. This document covers the features and customization options available for each column type. + +>**NOTE** +>Ensure that you have added the `syncfusion_flutter_datagrid` package to your `pubspec.yaml` file. For more information, refer to the [getting started with Flutter DataGrid](getting-started.md) documentation. ## GridColumn @@ -17,7 +20,7 @@ GridColumn is a class that provides base functionalities for all the column type ### Mapping column to a property -The column can be bound to a property in a data object using the [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) property. The [label](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/label.html) is used to display the required widget in a column header. +The column can be bound to a property in a data object using the [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) property. The [label](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/label.html) property is used to display the required widget in a column header. The `columnName` must match the property name in your data model for automatic data binding. {% tabs %} {% highlight Dart %} @@ -151,7 +154,7 @@ The column can be bound to a property in a data object using the [GridColumn.col ### Set manual width for a column -[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows you to customize the width of each [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) in the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) collection. To customize column width, use the [GridColumn.width](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/width.html) property. By default, this property will not be assigned any value. The GridColumn renders in view based on the value of the [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/defaultColumnWidth.html) property. +[SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows you to customize the width of each [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) in the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) collection. To customize column width, use the [GridColumn.width](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/width.html) property. Specify the width value in logical pixels. By default, this property will not be assigned any value, and the column renders based on the [SfDataGrid.defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/defaultColumnWidth.html) property. >**NOTE** >Set the `visible` property to `false` instead of setting column width as `0` to hide a column. @@ -220,9 +223,10 @@ The column can be bound to a property in a data object using the [GridColumn.col ## Checkbox column -By setting the [showCheckboxColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showCheckboxColumn.html) property to `true`, you can select or deselect individual rows using checkboxes in each row. The checkbox column will be added as the first column. +By setting the [showCheckboxColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showCheckboxColumn.html) property to `true`, you can select or deselect individual rows using checkboxes in each row. The checkbox column will be added as the first column in the grid. -The selection is applied to rows only if you set the [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property other than `none.` +>**NOTE** +>Row selection is applied only if you set the [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property to a value other than `none`. The checkbox state automatically synchronizes with the row selection state. {% tabs %} {% highlight Dart %} @@ -291,7 +295,7 @@ The selection is applied to rows only if you set the [SfDataGrid.selectionMode]( ### Show text in the header cell -Display widgets along with the checkbox in the header cell by adding a widget to the [SfDataGrid.checkboxColumnSettings.label](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/label.html) property. +Display widgets along with the checkbox in the header cell by adding a widget to the [DataGridCheckboxColumnSettings.label](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/label.html) property. This allows you to add custom text or icons above or beside the checkbox in the header. {% tabs %} {% highlight Dart %} @@ -362,9 +366,9 @@ Display widgets along with the checkbox in the header cell by adding a widget to ![flutter datagrid shows text in checkbox column header](images/column-types/flutter-datagrid-shows-text-in-checkbox-column-header.png) -### Disable the checkbox in the header cell +### Hide the checkbox in the header cell -By default, a checkbox is displayed in the header cell. By setting the [SfDataGrid.checkboxColumnSettings.showCheckboxOnHeader](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/showCheckboxOnHeader.html) property to `false`, the checkbox can be hidden in the header cell. +By default, a checkbox is displayed in the header cell. By setting the [DataGridCheckboxColumnSettings.showCheckboxOnHeader](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/showCheckboxOnHeader.html) property to `false`, the checkbox can be hidden from the header cell while keeping checkboxes in data rows. {% tabs %} {% highlight Dart %} @@ -435,7 +439,7 @@ By default, a checkbox is displayed in the header cell. By setting the [SfDataGr ### Change the background color of the checkbox column -The background color of the checkbox column can be customized by using the [SfDataGrid.checkboxColumnSettings.backgroundColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/backgroundColor.html) property. +The background color of the entire checkbox column can be customized by using the [DataGridCheckboxColumnSettings.backgroundColor](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxColumnSettings/backgroundColor.html) property. This property affects both the header and data rows of the checkbox column. {% tabs %} {% highlight Dart %} @@ -506,7 +510,10 @@ The background color of the checkbox column can be customized by using the [SfDa ### Get checked items -Get the checked items by using the [DataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) property because the selection and checkbox's checked states are the same. +Get the checked items by using the [DataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) property. The checkbox state and row selection state are synchronized, so you can retrieve checked rows through the controller's selection properties. + +>**NOTE** +>Ensure the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) is assigned to the `SfDataGrid.controller` property for programmatic access to selection information. {% tabs %} {% highlight Dart %} @@ -596,7 +603,7 @@ Get the checked items by using the [DataGridController.selectedRows](https://pub ### Change the shape of the checkbox column -By default, the checkbox shows in the DataGrid as a square shape. Change the checkbox shape by setting the required shape in the [SfDataGrid.checkboxShape](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/checkboxShape.html) property. +By default, checkboxes in the DataGrid appear as a square shape. Change the checkbox shape by setting the required [`ShapeBorder`](https://api.flutter.dev/flutter/material/ShapeBorder-class.html) in the [SfDataGrid.checkboxShape](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/checkboxShape.html) property. You can use built-in shapes like `CircleBorder()`, `RoundedRectangleBorder()`, or create a custom shape. {% tabs %} {% highlight Dart %} @@ -659,11 +666,11 @@ The `SfDataGrid` provides the following callback for checkbox interactions: * [onCheckboxValueChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onCheckboxValueChanged.html): This callback is triggered when the checkbox is selected or deselected, either by tapping on the checkbox or by selecting or deselecting a row (i.e., when the value of the checkbox changes). -The checkbox callbacks provide the following properties in their arguments: +The [DataGridCheckboxValueChangedDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails-class.html) object passed to the callback provides the following properties: -* [value](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/value.html): Represents the current state of the checkbox. -* [row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/row.html): Refers to the DataGridRow linked to the checkbox in the checkbox column. If the checkbox is part of a column header, the value will be null, indicating that it is not linked to any specific data row. -* [rowType](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/rowType.html): Defines the type of row associated with the checkbox. It indicates whether the checkbox value in a data row or header row has been modified. +* [value](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/value.html): A boolean representing the current state of the checkbox (`true` if checked, `false` if unchecked). +* [row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/row.html): The [DataGridRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRow-class.html) linked to the checkbox. If the checkbox is part of a column header, this value will be null. +* [rowType](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCheckboxValueChangedDetails/rowType.html): A [RowType](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowType.html) enum value that indicates whether the checkbox is in a data row or header row. {% tabs %} {% highlight Dart %} @@ -722,15 +729,18 @@ The checkbox callbacks provide the following properties in their arguments: ### Limitations -The following are the limitations of GridCheckboxColumn: +The following are the limitations of the checkbox column: + +* The checkbox column does not support sorting or other data operations. +* The checkbox column does not support stacked headers in combination with other columns. +* The checkbox column is excluded from exporting operations (PDF, Excel, etc.). -* The checkbox column does not support data operations such as sorting. -* The checkbox column does not support adding the stacked headers along with other columns. -* The checkbox column will be excluded in exporting operations. +## Column header icons on hover -## Show the column header icons on hover +To display column header icons, such as sort and filter icons, when the mouse hovers over a column header, set the [SfDataGrid.showColumnHeaderIconOnHover](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showColumnHeaderIconOnHover.html) property to `true`. This feature is available only on web and desktop platforms. -To display column header icons, such as sort and filter icons, when the mouse hovers over a column header, set the [SfDataGrid.showColumnHeaderIconOnHover](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showColumnHeaderIconOnHover.html) property to true. This feature is available only on web and desktop platforms. +>**NOTE** +>This feature requires the [SfDataGrid.allowSorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowSorting.html) or [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) properties to be enabled for the icons to appear. {% tabs %} {% highlight Dart %} @@ -801,4 +811,10 @@ To display column header icons, such as sort and filter icons, when the mouse ho {% endhighlight %} {% endtabs %} -flutter datagrid shows column header icons when hover over the header cell \ No newline at end of file +flutter datagrid shows column header icons when hover over the header cell + +## See also + +* [DataGrid getting started](getting-started.md) +* [GitHub sample repository](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid) +* [SfDataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) \ No newline at end of file diff --git a/Flutter/datagrid/columns-resizing.md b/Flutter/datagrid/columns-resizing.md index e30200ab7..7201bfdd0 100644 --- a/Flutter/datagrid/columns-resizing.md +++ b/Flutter/datagrid/columns-resizing.md @@ -11,18 +11,25 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support to resize the columns by dragging the right end of the column header. The column resizing can be enabled by setting the [SfDataGrid.allowColumnsResizing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowColumnsResizing.html) property to `true`. +>**Note** +>Ensure you have added the `syncfusion_flutter_datagrid` package to your project. For setup instructions, refer to the [getting started](getting-started.md) documentation. + `SfDataGrid` does not automatically resize the columns when you perform column resizing. You should maintain the column width collection at the application level and set the column width of the corresponding column using the [SfDataGrid.onColumnResizeUpdate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeUpdate.html) callback. The column resizing indicator appears based on the platform. In web and desktop platforms, the indicator appears when you hover over the right end of the column and drag it. In mobile platforms, the indicator comes into view when you long-press the corresponding column header. > **NOTE:** -> Column resizing considers the [GridColumn.minimumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/minimumWidth.html) and [GridColumn.maximumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/maximumWidth.html) properties. +> Column resizing considers the [GridColumn.minimumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/minimumWidth.html) and [GridColumn.maximumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/maximumWidth.html) properties. These limits are enforced to prevent columns from becoming too small or too large during resizing. + +## Basic Column Resizing + +The following example demonstrates the basic column resizing setup. The `columnWidths` map stores the width of each column. Using `double.nan` as initial values allows the DataGrid to use default column width sizing until the user manually resizes a column. {% tabs %} {% highlight Dart %} late Map columnWidths = { - 'id': double.nan, + 'id': double.nan, // double.nan means use default width until resized 'name': double.nan, 'designation': double.nan, 'salary': double.nan @@ -99,8 +106,8 @@ The column resizing indicator appears based on the platform. In web and desktop By default, the columns are resized by dragging the right end of the columns. `SfDataGrid` provides two modes to perform column resizing: -* `onResize`: The resizing indicator moves based on the dragging gesture. `onColumnResizeUpdate` callback is called when a column is resized. -* `onResizeEnd`: The resizing indicator moves based on the dragging gesture. `onColumnResizeUpdate` callback is called when you release the pointer. +* `onResize`: The resizing indicator moves based on the dragging gesture. `onColumnResizeUpdate` callback is called continuously as the user drags. Use this mode when you want real-time column width updates. +* `onResizeEnd`: The resizing indicator moves based on the dragging gesture. `onColumnResizeUpdate` callback is called only when you release the pointer. Use this mode for better performance when handling expensive operations like persisting changes. The following example demonstrates how to resize a column by setting the [SfDataGrid.columnResizeMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnResizeMode.html) property to `onResizeEnd`. @@ -186,9 +193,9 @@ The following example demonstrates how to resize a column by setting the [SfData The following callbacks are called when you perform column resizing: -* [onColumnResizeStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeStart.html): Called when column resizing is started. In mobile platforms, it will be called when the resizing indicator appears after you long-press the corresponding column header. In web and desktop platforms, it will be called when you click and drag the right end of the columns. -* `onColumnResizeUpdate`: Called when a column is being resized. Typically, you should set the column width here. -* [onColumnResizeEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeEnd.html): Called when column resizing is ended. Typically, this will be called when you release the pointer. +* [onColumnResizeStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeStart.html): Called when column resizing is started. In mobile platforms, it will be called when the resizing indicator appears after you long-press the corresponding column header. In web and desktop platforms, it will be called when you click and drag the right end of the columns. Return `true` to allow resizing, or `false` to prevent it. +* `onColumnResizeUpdate`: Called when a column is being resized. Typically, you should set the column width here. The callback provides `ColumnResizeUpdateDetails` with properties: `column` (the GridColumn being resized) and `width` (the new width). Return `true` to apply the change. +* [onColumnResizeEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeEnd.html): Called when column resizing is ended. This will be called when you release the pointer. The callback provides `ColumnResizeEndDetails` with the final column and width information. {% tabs %} {% highlight Dart %} @@ -273,7 +280,7 @@ The following callbacks are called when you perform column resizing: ## Disable resizing for a particular column -To disable resizing for a particular column, use the `SfDataGrid.onColumnResizeStart` callback and return `false` to the corresponding column. Return `true` for all other columns. +To disable resizing for a particular column, return `false` in the `onColumnResizeStart` callback for that column. Return `true` for all other columns to allow resizing. {% tabs %} {% highlight Dart %} @@ -359,7 +366,7 @@ To disable resizing for a particular column, use the `SfDataGrid.onColumnResizeS ## Disable resizing for the checkbox column -The checkbox column is always added as the first column (index 0). To disable resizing for the checkbox column, use the `SfDataGrid.onColumnResizeStart` callback and return false when the [ColumnResizeStartDetails.columnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnResizeStartDetails/columnIndex.html) is 0. +When checkbox selection is enabled (`showCheckboxColumn: true`), the checkbox column is always added as the first column (index 0). To disable resizing for the checkbox column, return `false` in the `onColumnResizeStart` callback when the [ColumnResizeStartDetails.columnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnResizeStartDetails/columnIndex.html) is `0`. {% tabs %} {% highlight Dart %} @@ -525,11 +532,25 @@ To prevent a column from being hidden while resizing, use the `GridColumn.minimu {% endhighlight %} {% endtabs %} +## Troubleshooting + +**Column widths not persisting after app restart?** +Column width changes are stored in memory during the session. To persist widths across app restarts, save the `columnWidths` map to local storage (using packages like `shared_preferences` or `hive`) in the `onColumnResizeUpdate` callback, and restore the values when the widget initializes. + +**Columns not resizing visually?** +Ensure that `onColumnResizeUpdate` returns `true` and that `columnWidths` map is properly updated in `setState()`. Also verify that the column width is not set to a fixed value that overrides the resized width. + +**Resizing feels sluggish?** +Use `columnResizeMode: ColumnResizeMode.onResizeEnd` instead of the default `onResize` mode to reduce callback frequency and improve performance. + ## Customize indicator appearance The column resizing indicator color and its width can be customized by using the [SfDataGridThemeData.columnResizeIndicatorColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnResizeIndicatorColor.html) and [SfDataGridThemeData.columnResizeIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnResizeIndicatorStrokeWidth.html) properties. -The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. So, import the following file: +>**Note** +>The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. Ensure this package is added to your project dependencies. + +Import the following file: {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/columns-sizing.md b/Flutter/datagrid/columns-sizing.md index 771a7a8f6..556f8040c 100644 --- a/Flutter/datagrid/columns-sizing.md +++ b/Flutter/datagrid/columns-sizing.md @@ -9,24 +9,38 @@ documentation: ug # Column sizing in Flutter DataGrid (SfDataGrid) +> **NOTE** + Ensure that SfDataGrid is installed and configured in your Flutter project. Refer to the [getting started guide](getting-started.md) for setup instructions. + [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows setting the column widths based on certain logic using the [SfDataGrid.columnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthMode.html) or [GridColumn.columnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnWidthMode.html) property. The following is the list of predefined column sizing options available. | Mode | Description | |---------------------------|-----------------------------------------------------| -| ColumnWidthMode.auto | Calculates the width of column based on [GridColumn.columName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) and [DataGridCell.value](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCell/value.html) properties. So, the header and cell contents are not truncated. | +| ColumnWidthMode.auto | Calculates the width of column based on [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) and [DataGridCell.value](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCell/value.html) properties. So, the header and cell contents are not truncated. | | ColumnWidthMode.fitByCellValue | Calculates the width of column based on `DataGridCell.value` property. So, the cell contents are not truncated. | | ColumnWidthMode.fitByColumnName | Calculates the width of column based on `GridColumn.columName` property. So, the header contents are not truncated. | | ColumnWidthMode.lastColumnFill | Applies default Column width to all the columns except last column which is visible and the remaining width from total width of SfDataGrid is set to last column. | | ColumnWidthMode.fill | Divides the total width equally for columns. | -| ColumnWidthMode.none | No sizing. Default column width or defined width set to column. | +| ColumnWidthMode.none | No sizing. Default column width (80.0) or explicitly defined width is set to the column. | > **NOTE** - [ColumnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthMode.html) will not work when the column width defined explicitly. `columnWidthMode` calculates column width based on miniumWidth and maximumWidth properties. + [ColumnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthMode.html) will not work when the column width is defined explicitly. `columnWidthMode` calculates column width based on `minimumWidth` and `maximumWidth` properties. For optimal performance with large datasets, consider using `ColumnWidthMode.none` or `ColumnWidthMode.fill` instead of `ColumnWidthMode.auto`. The following example shows how to set the width equally for columns based on the viewport size. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } @override Widget build(BuildContext context) { @@ -68,7 +82,7 @@ The following example shows how to set the width equally for columns based on th padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, child: Text( - 'city', + 'City', overflow: TextOverflow.ellipsis, ))), GridColumn( @@ -96,7 +110,18 @@ The `GridColumn.columnWidthMode` takes higher priority than the `SfDataGrid.colu By default, the autofit calculation is performed for only visible rows. You can use the [SfDataGrid.columnWidthCalculationRange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthCalculationRange.html) property as [ColumnWidthCalculationRange.allRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthCalculationRange.html) to perform the autofit calculation for all the available rows. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } @override Widget build(BuildContext context) { @@ -106,7 +131,7 @@ By default, the autofit calculation is performed for only visible rows. You can columnWidthCalculationRange: ColumnWidthCalculationRange.allRows, columns: [ GridColumn( - columnName: 'ID', + columnName: 'id', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerRight, @@ -115,7 +140,7 @@ By default, the autofit calculation is performed for only visible rows. You can softWrap: false, ))), GridColumn( - columnName: 'Name', + columnName: 'name', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerLeft, @@ -124,7 +149,7 @@ By default, the autofit calculation is performed for only visible rows. You can softWrap: false, ))), GridColumn( - columnName: 'Designation', + columnName: 'designation', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerLeft, @@ -133,7 +158,7 @@ By default, the autofit calculation is performed for only visible rows. You can softWrap: false, ))), GridColumn( - columnName: 'Salary', + columnName: 'salary', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerRight, @@ -149,13 +174,24 @@ By default, the autofit calculation is performed for only visible rows. You can ## Change the padding value for autofit calculation -By default, the EdgeInsets.all(16.0) is added with the auto width or height value. You can change the padding for specific columns by using the [GridColumn.autoFitPadding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/autoFitPadding.html) property. +By default, `EdgeInsets.all(16.0)` is added with the auto width or height value. You can change the padding for specific columns by using the [GridColumn.autoFitPadding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/autoFitPadding.html) property. You can also use asymmetric padding values (e.g., `EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0)`) for fine-grained control. >**NOTE** -`GridColumn.autoFitPadding` is applicable for header cell also. +`GridColumn.autoFitPadding` is applicable for header cells as well. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } @override Widget build(BuildContext context) { @@ -206,15 +242,24 @@ By default, the EdgeInsets.all(16.0) is added with the auto width or height valu ]); } +class Employee { + final int id; + final String name; + final String designation; + final int salary; + + Employee({required this.id, required this.name, required this.designation, required this.salary}); +} + class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { _employeeData = employees .map((e) => DataGridRow(cells: [ - DataGridCell(columnName: 'ID', value: e.id), - DataGridCell(columnName: 'Name', value: e.name), + DataGridCell(columnName: 'id', value: e.id), + DataGridCell(columnName: 'name', value: e.name), DataGridCell( - columnName: 'Designation', value: e.designation), - DataGridCell(columnName: 'Salary', value: e.salary), + columnName: 'designation', value: e.designation), + DataGridCell(columnName: 'salary', value: e.salary), ])) .toList(); } @@ -238,6 +283,15 @@ class EmployeeDataSource extends DataGridSource { } } +List getEmployeeData() { + return [ + Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), + Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), + ]; +} + {% endhighlight %} {% endtabs %} @@ -245,12 +299,22 @@ class EmployeeDataSource extends DataGridSource { ## Autofit calculation based on different TextStyle -By default, the cell width is calculated based on the default text style. To calculate the cell width based on different [TextStyle](https://api.flutter.dev/flutter/painting/TextStyle-class.html), just override the [computeHeaderCellWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer/computeHeaderCellWidth.html) method for the header and [computeCellWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer/computeCellWidth.html) method for the cell and return the super method with the required `TextStyle.` +By default, the cell width is calculated based on the default text style. To calculate the cell width based on different [TextStyle](https://api.flutter.dev/flutter/painting/TextStyle-class.html), override the [computeHeaderCellWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer/computeHeaderCellWidth.html) method for the header and [computeCellWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnSizer/computeCellWidth.html) method for the cell, and return the super method with the required `TextStyle`. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } @override Widget build(BuildContext context) { @@ -260,7 +324,7 @@ By default, the cell width is calculated based on the default text style. To cal columnWidthMode: ColumnWidthMode.auto, columns: [ GridColumn( - columnName: 'ID', + columnName: 'id', autoFitPadding: EdgeInsets.all(12.0), label: Container( padding: EdgeInsets.all(12.0), @@ -269,7 +333,7 @@ By default, the cell width is calculated based on the default text style. To cal 'ID', ))), GridColumn( - columnName: 'Name', + columnName: 'name', autoFitPadding: EdgeInsets.all(12.0), label: Container( padding: EdgeInsets.all(12.0), @@ -280,7 +344,7 @@ By default, the cell width is calculated based on the default text style. To cal fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), ))), GridColumn( - columnName: 'Designation', + columnName: 'designation', autoFitPadding: EdgeInsets.all(12.0), label: Container( padding: EdgeInsets.all(12.0), @@ -292,7 +356,7 @@ By default, the cell width is calculated based on the default text style. To cal fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), ))), GridColumn( - columnName: 'Salary', + columnName: 'salary', autoFitPadding: EdgeInsets.all(12.0), label: Container( padding: EdgeInsets.all(12.0), @@ -301,15 +365,24 @@ By default, the cell width is calculated based on the default text style. To cal ]); } +class Employee { + final int id; + final String name; + final String designation; + final int salary; + + Employee({required this.id, required this.name, required this.designation, required this.salary}); +} + class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { _employeeData = employees .map((e) => DataGridRow(cells: [ - DataGridCell(columnName: 'ID', value: e.id), - DataGridCell(columnName: 'Name', value: e.name), + DataGridCell(columnName: 'id', value: e.id), + DataGridCell(columnName: 'name', value: e.name), DataGridCell( - columnName: 'Designation', value: e.designation), - DataGridCell(columnName: 'Salary', value: e.salary), + columnName: 'designation', value: e.designation), + DataGridCell(columnName: 'salary', value: e.salary), ])) .toList(); } @@ -327,7 +400,7 @@ class EmployeeDataSource extends DataGridSource { alignment: Alignment.center, padding: EdgeInsets.all(12.0), child: Text(e.value.toString(), - style: (e.columnName == 'Name' || e.columnName == 'Designation') + style: (e.columnName == 'name' || e.columnName == 'designation') ? TextStyle( fontWeight: FontWeight.bold, fontStyle: FontStyle.italic) : null)); @@ -338,7 +411,7 @@ class EmployeeDataSource extends DataGridSource { class CustomColumnSizer extends ColumnSizer { @override double computeHeaderCellWidth(GridColumn column, TextStyle style) { - if (column.columnName == 'Name' || column.columnName == 'Designation') { + if (column.columnName == 'name' || column.columnName == 'designation') { style = TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic); } @@ -348,7 +421,7 @@ class CustomColumnSizer extends ColumnSizer { @override double computeCellWidth(GridColumn column, DataGridRow row, Object? cellValue, TextStyle textStyle) { - if (column.columnName == 'Name' || column.columnName == 'Designation') { + if (column.columnName == 'name' || column.columnName == 'designation') { textStyle = TextStyle(fontWeight: FontWeight.bold, fontStyle: FontStyle.italic); } @@ -356,24 +429,39 @@ class CustomColumnSizer extends ColumnSizer { } } -{% endhighlight %} -{% endtabs %} +List getEmployeeData() { + return [ + Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), + Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), + ]; +} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-column-based-on-the-different-text-style-in-Flutter-DataTable-sfdatagrid). +{% endhighlight %} +{% endtabs %} ![flutter datagrid shows autofit the columns based on different text style](images/autofit-columns/flutter-datagrid-textstyle-customization.png) ## Autofit calculation based on the formatted value -The cell width is calculated by default based on the `DataGridCell.value` property. To autofit the cell width based on the displayed formatted value (This is, DateFormat and NumberFormat), simply override the `computeCellWidth` method and return the super method with the required `cellValue.` +The cell width is calculated by default based on the `DataGridCell.value` property. To autofit the cell width based on the displayed formatted value (that is, DateFormat and NumberFormat), override the `computeCellWidth` method and return the super method with the required `cellValue`. {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getFormattedEmployeeData()); + } @override Widget build(BuildContext context) { @@ -383,7 +471,7 @@ import 'package:intl/intl.dart'; columnWidthMode: ColumnWidthMode.fitByCellValue, columns: [ GridColumn( - columnName: 'ID', + columnName: 'id', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerRight, @@ -392,7 +480,7 @@ import 'package:intl/intl.dart'; softWrap: false, ))), GridColumn( - columnName: 'Name', + columnName: 'name', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerLeft, @@ -401,7 +489,7 @@ import 'package:intl/intl.dart'; softWrap: false, ))), GridColumn( - columnName: 'DOB', + columnName: 'dob', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerLeft, @@ -410,7 +498,7 @@ import 'package:intl/intl.dart'; softWrap: false, ))), GridColumn( - columnName: 'Salary', + columnName: 'salary', label: Container( padding: EdgeInsets.all(16.0), alignment: Alignment.centerRight, @@ -421,14 +509,23 @@ import 'package:intl/intl.dart'; ]); } +class Employee { + final int id; + final String name; + final DateTime dob; + final int salary; + + Employee({required this.id, required this.name, required this.dob, required this.salary}); +} + class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { _employeeData = employees .map((e) => DataGridRow(cells: [ - DataGridCell(columnName: 'ID', value: e.id), - DataGridCell(columnName: 'Name', value: e.name), - DataGridCell(columnName: 'DOB', value: e.dob), - DataGridCell(columnName: 'Salary', value: e.salary), + DataGridCell(columnName: 'id', value: e.id), + DataGridCell(columnName: 'name', value: e.name), + DataGridCell(columnName: 'dob', value: e.dob), + DataGridCell(columnName: 'salary', value: e.salary), ])) .toList(); } @@ -443,9 +540,9 @@ class EmployeeDataSource extends DataGridSource { return DataGridRowAdapter( cells: row.getCells().map((e) { late String cellValue; - if (e.columnName == 'DOB') { + if (e.columnName == 'dob') { cellValue = DateFormat.yMMMMd('en_US').format(e.value); - } else if (e.columnName == 'Salary') { + } else if (e.columnName == 'salary') { cellValue = NumberFormat.simpleCurrency(decimalDigits: 0).format(e.value); } else { @@ -465,9 +562,9 @@ class CustomColumnSizer extends ColumnSizer { @override double computeCellWidth(GridColumn column, DataGridRow row, Object? cellValue, TextStyle textStyle) { - if (column.columnName == 'DOB') { + if (column.columnName == 'dob') { cellValue = DateFormat.yMMMMd('en_US').format(cellValue as DateTime); - } else if (column.columnName == 'Salary') { + } else if (column.columnName == 'salary') { cellValue = NumberFormat.simpleCurrency(decimalDigits: 0).format(cellValue); } @@ -476,20 +573,37 @@ class CustomColumnSizer extends ColumnSizer { } } -{% endhighlight %} -{% endtabs %} +List getFormattedEmployeeData() { + return [ + Employee(id: 10001, name: 'James', dob: DateTime(1990, 5, 15), salary: 60000), + Employee(id: 10002, name: 'Kathryn', dob: DateTime(1992, 8, 22), salary: 30000), + Employee(id: 10003, name: 'Lara', dob: DateTime(1995, 3, 10), salary: 15000), + Employee(id: 10004, name: 'Michael', dob: DateTime(1993, 12, 5), salary: 15000), + ]; +} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-columns-based-on-the-formatted-value-in-Flutter-datatable-sfdatagrid). +{% endhighlight %} +{% endtabs %} ![flutter datagrid shows autofit the columns based on formatted cell value](images/autofit-columns/flutter-datagrid-formatted-cellvalue.png) ## Fill the remaining width for any column -While setting `SfDataGrid.columnWidthMode` as `lastColumnFill` the remaining width is applied to the last column. The remaining width of a specific column can be applied by setting the `GridColumn.columnWidthMode` property. +While setting `SfDataGrid.columnWidthMode` as `lastColumnFill`, the remaining width is applied to the last column. The remaining width of a specific column can be applied by setting the `GridColumn.columnWidthMode` property. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } @override Widget build(BuildContext context) { @@ -542,11 +656,22 @@ While setting `SfDataGrid.columnWidthMode` as `lastColumnFill` the remaining wi ![The last column is filled in view in flutter datagrid](images/autofit-columns/flutter-datagrid-fill-lastcolumn.png) -The below example shows Name column is set as `lastColumnFill` mode. +The following example shows Name column is set as `lastColumnFill` mode. {% tabs %} -{% highlight Dart %} - +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -600,12 +725,25 @@ The below example shows Name column is set as `lastColumnFill` mode. ## Recalculating column widths when datasource is changed -By default, column widths are calculated based on the `columnWidthMode` property on the initial loading of the Datagrid. When the data source is changed for the same datagrid at run time, the Datagrid does not recalculate the column widths. To recalculate the column widths at run time when the data source is changed or data is updated, override the [shouldRecalculateColumnWidths](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/shouldRecalculateColumnWidths.html) method and return `true.` - -Returning true may impact performance as the column widths are recalculated again (whenever the notifyListeners is called). If you know that column widths will be the same whenever underlying data changes, return `false` from this method. +By default, column widths are calculated based on the `columnWidthMode` property on the initial loading of the DataGrid. When the data source is changed for the same DataGrid at run time, the DataGrid does not recalculate the column widths. To recalculate the column widths at run time when the data source is changed or data is updated, override the [shouldRecalculateColumnWidths](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/shouldRecalculateColumnWidths.html) method and return `true`. Then, call `notifyListeners()` to trigger the recalculation. + +> **NOTE** +Returning `true` may impact performance as the column widths are recalculated whenever `notifyListeners()` is called. If you know that column widths will be the same whenever underlying data changes, return `false` from this method. {% tabs %} -{% highlight Dart %} +{% highlight Dart %} + +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + +class Employee { + final int id; + final String name; + final String designation; + final int salary; + + Employee({required this.id, required this.name, required this.designation, required this.salary}); +} class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { @@ -647,6 +785,30 @@ class EmployeeDataSource extends DataGridSource { bool shouldRecalculateColumnWidths() { return true; } + + // Call this method when data is updated to recalculate column widths + void updateData(List employees) { + dataGridRows = employees + .map((dataGridRow) => DataGridRow(cells: [ + DataGridCell(columnName: 'id', value: dataGridRow.id), + DataGridCell(columnName: 'name', value: dataGridRow.name), + DataGridCell( + columnName: 'designation', value: dataGridRow.designation), + DataGridCell( + columnName: 'salary', value: dataGridRow.salary), + ])) + .toList(); + notifyListeners(); + } +} + +List getEmployeeData() { + return [ + Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), + Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), + ]; } {% endhighlight %} diff --git a/Flutter/datagrid/conditional-styling.md b/Flutter/datagrid/conditional-styling.md index 26a0408a0..2018419cd 100644 --- a/Flutter/datagrid/conditional-styling.md +++ b/Flutter/datagrid/conditional-styling.md @@ -1,7 +1,7 @@ --- layout: post -title: Conditional Styling in Flutter DataGrid | DataTable | Syncfusion -description: Learn here all about how to style the rows and columns in Syncfusion Flutter DataGrid (SfDataGrid) widget and more. +title: Conditional Styling in Flutter DataGrid | SfDataGrid | Syncfusion +description: Learn here all about how to style the rows and cells in Syncfusion Flutter DataGrid (SfDataGrid) widget and more. platform: flutter control: SfDataGrid documentation: ug @@ -11,11 +11,38 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows customizing the style of individual cells and rows based on your requirements. You can customize your widget in the `DataGridSource.buildRow` method with the help of `DataGridRowAdapter`. +> **Note:** Ensure you have added the `syncfusion_flutter_datagrid` package to your project's `pubspec.yaml` file. Refer to the [getting-started](getting-started.md) guide for installation instructions. + +## Employee Model Class + +The following examples use an `Employee` model class. Define it as shown below: + +```dart +class Employee { + Employee({ + required this.id, + required this.name, + required this.designation, + required this.salary, + }); + + final int id; + final String name; + final String designation; + final int salary; +} +``` + +## When to Use Cell-Level vs Row-Level Styling + +- **Cell-level styling:** Use when you need to style specific cells based on their individual content or column type. This allows fine-grained control over individual cell appearance. +- **Row-level styling:** Use when you want to apply consistent styling across an entire row based on row data. This is more efficient for styling multiple cells at once. + ## Cells ### Styling based on content -The appearance of cells in `SfDataGrid` can be customized conditionally based on their content by setting your widget to the `DataGridRowAdapter.cells`. +Customize the appearance of cells conditionally based on their content by defining custom widgets in the `DataGridRowAdapter.cells` property. In the example below, cells in the designation column are styled with different background colors and text styles based on their values. {% tabs %} {% highlight Dart %} @@ -148,7 +175,7 @@ class EmployeeDataSource extends DataGridSource { ### Styling alternate cells -The appearance of alternating cells in a column can be customized conditionally by using the `DataGridSource.buildRow` method. +Customize the appearance of alternating cells in a column by using the `DataGridSource.buildRow` method and the `effectiveRows` property to determine the row index. The `effectiveRows` property contains the sorted collection of rows if sorting is applied. {% tabs %} {% highlight Dart %} @@ -215,7 +242,7 @@ class EmployeeDataSource extends DataGridSource { ### Styling based on content -The appearance of rows in `SfDataGrid` can be customized conditionally based on the content using `DataGridRowAdapter.color`. +Customize the appearance of rows conditionally based on their content using the `DataGridRowAdapter.color` property. In the example below, rows are styled with different background and text colors based on salary values. {% tabs %} {% highlight Dart %} @@ -290,7 +317,7 @@ class EmployeeDataSource extends DataGridSource { ### Styling alternate rows -The appearance of the alternating rows in `SfDataGrid` can be customized using the `DataGridRowAdapter.color`. Use the [effectiveRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/effectiveRows.html) property to get the index of the row. This collection contains the sorted collection if the sorting is applied. +Customize the appearance of alternating rows in `SfDataGrid` using the `DataGridRowAdapter.color` property. Use the [effectiveRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/effectiveRows.html) property to get the row index. The `effectiveRows` collection contains sorted rows when sorting is applied, ensuring alternate row styling works correctly with sorted data. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/data-binding.md b/Flutter/datagrid/data-binding.md index 0de91d2b5..ff88327a3 100644 --- a/Flutter/datagrid/data-binding.md +++ b/Flutter/datagrid/data-binding.md @@ -15,15 +15,28 @@ The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/lates * [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) - The number of rows in a Datagrid and row selection depends on the `rows.` Set the `DataGridRow` collection required for Datagrid in `rows`. -* [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) - The widget needed for the cells is obtained from `DataGridRowAdapter`. +* [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) - The widgets for cells are built using `DataGridRowAdapter`. `DataGridSource` objects are expected to be long-lived, not recreated with each build. +N> Ensure the `columnName` property in `DataGridCell` matches the `columnName` in the corresponding `GridColumn` definitions. This alignment is essential for the DataGrid to correctly display and manage the data. + The following example shows how to create the `DataGridSource`, {% tabs %} {% highlight dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + +class Employee { + Employee(this.id, this.name, this.designation, this.salary); + final int id; + final String name; + final String designation; + final int salary; +} + class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { dataGridRows = employees @@ -69,23 +82,33 @@ The following example shows how to set the `source` property in `SfDataGrid` {% tabs %} {% highlight dart %} - late EmployeeDataSource _employeeDataSource; - List _employees = []; +List getEmployeeData() { + return [ + Employee(1001, 'James', 'Project Manager', 20000), + Employee(1002, 'Kathryn', 'Manager', 30000), + Employee(1003, 'Lara', 'Developer', 15000), + Employee(1004, 'Michael', 'Developer', 15000), + Employee(1005, 'Martin', 'Developer', 15000), + ]; +} - @override - void initState() { - super.initState(); - _employees = getEmployeeData(); - _employeeDataSource = EmployeeDataSource(employees: _employees); - } +late EmployeeDataSource _employeeDataSource; +List _employees = []; + +@override +void initState() { + super.initState(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employees: _employees); +} @override - Widget build(BuildContext context) { - return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columnWidthMode: ColumnWidthMode.lastColumnFill, - columns: [ +Widget build(BuildContext context) { + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.lastColumnFill, + columns: [ GridColumn( columnName: 'id', label: Container( @@ -123,86 +146,100 @@ The following example shows how to set the `source` property in `SfDataGrid` overflow: TextOverflow.ellipsis, ))) ])); - } +} {% endhighlight %} {% endtabs %} +N> `ColumnWidthMode.lastColumnFill` automatically adjusts the width of the last column to fill any remaining space in the DataGrid. + ## Data manipulation in Flutter DataGrid (SfDataGrid) -`SfDataGrid` provides support to update or refresh the DataGrid when underlying data is updated (i.e. CRUD operation is performed in an underlying data). +`SfDataGrid` provides support to update or refresh the DataGrid when underlying data is updated via CRUD operations. -If a row is added, removed, or replaced in an underlying data source, call the [notifyListeners](https://api.flutter.dev/flutter/foundation/ChangeNotifier/notifyListeners.html). +N> `notifyListeners` must be called from inside the `DataGridSource`. Since it is a protected method, wrap it in a public method like `updateDataGridSource` that can be called from the widget level. -In the following example, a row is added, and `notifyListeners` is called in the `onPressed` callback of the `TextButton`. Since `notifyListeners` is a protected method, the `updateDataGridSource` method the `notifyListeners` method. You can call the `updateDataGridSource` methods at the widget level to refresh the Datagrid. +N> Requires `syncfusion_flutter_datagrid` package version 20.0.0 or later. -N> `notifyListeners` should be called from inside the `DataGridSource`. +If a row is added, removed, or replaced in an underlying data source, call the [notifyListeners](https://api.flutter.dev/flutter/foundation/ChangeNotifier/notifyListeners.html) method to notify the DataGrid to refresh. + +In the following example, a row is added, and `notifyListeners` is called through the `updateDataGridSource` method in the `onPressed` callback of the `TextButton`. {% tabs %} {% highlight Dart %} - - final List _employees = []; - final EmployeeDataSource _employeeDataSource = EmployeeDataSource(); - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column(children: [ - TextButton( - child: const Text('Add row'), - onPressed: () { - _employees.add(Employee(10011, 'Steve', 'Designer', 15000)); - _employeeDataSource.buildDataGridRows(); - _employeeDataSource.updateDataGridSource(); - }), - SfDataGrid(source: _employeeDataSource, columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ]) - ])); - } +List getEmployeeData() { + return [ + Employee(1001, 'James', 'Project Manager', 20000), + Employee(1002, 'Kathryn', 'Manager', 30000), + Employee(1003, 'Lara', 'Developer', 15000), + ]; +} -class EmployeeDataSource extends DataGridSource { - EmployeeDataSource() { - buildDataGridRows(); - } +final List _employees = getEmployeeData(); +final EmployeeDataSource _employeeDataSource = EmployeeDataSource(); - void buildDataGridRows() { - dataGridRows = _employees +@override +void initState() { + super.initState(); + _employeeDataSource.buildDataGridRows(_employees); +} + +@override +Widget build(BuildContext context) { + return Scaffold( + body: Column(children: [ + TextButton( + child: const Text('Add row'), + onPressed: () { + _employees.add(Employee(10011, 'Steve', 'Designer', 15000)); + _employeeDataSource.buildDataGridRows(_employees); + _employeeDataSource.updateDataGridSource(); + }), + SfDataGrid(source: _employeeDataSource, columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ))) + ]) + ])); +} + +class EmployeeDataSource extends DataGridSource { + void buildDataGridRows(List employees) { + dataGridRows = employees .map((dataGridRow) => DataGridRow(cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), @@ -244,87 +281,96 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -If the value of a specific cell is updated, you can call the `notifyDataSourceListeners` method with the [RowColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowColumnIndex-class.html) argument, which refers to the corresponding row and column index of the cell. -This way, DataGrid refreshes only the corresponding cell alone. +If the value of a specific cell is updated, you can call the `notifyDataSourceListeners` method with the [RowColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowColumnIndex-class.html) argument to refresh only that specific cell, improving performance by avoiding unnecessary full DataGrid refreshes. The `RowColumnIndex` takes two parameters: row index and column index (both 0-based). -In the following example, a cell value is updated, and `notifyDataSourceListeners` is called in the `onPressed` callback of the `TextButton.` +In the following example, a cell value is updated, and `notifyDataSourceListeners` is called in the `onPressed` callback of the `TextButton` with `RowColumnIndex(0, 3)` to refresh only the salary cell in the first row. {% tabs %} {% highlight Dart %} - final List _employees = []; - final EmployeeDataSource _employeeDataSource = EmployeeDataSource(); +List getEmployeeData() { + return [ + Employee(1001, 'James', 'Project Manager', 20000), + Employee(1002, 'Kathryn', 'Manager', 30000), + Employee(1003, 'Lara', 'Developer', 15000), + ]; +} - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: Column(children: [ - TextButton( - child: const Text('Update cell value'), - onPressed: () { - _employees[0].salary = 25000; - _employeeDataSource.dataGridRows[0] = DataGridRow(cells: [ - DataGridCell(value: _employees[0].id, columnName: 'id'), - DataGridCell(value: _employees[0].name, columnName: 'name'), - DataGridCell( - value: _employees[0].designation, - columnName: 'designation'), - DataGridCell(value: _employees[0].salary, columnName: 'salary'), - ]); - _employeeDataSource.updateDataGridSource( - rowColumnIndex: RowColumnIndex(0, 3)); - }), - SfDataGrid(source: _employeeDataSource, columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ]) - ])); - } +final List _employees = getEmployeeData(); +final EmployeeDataSource _employeeDataSource = EmployeeDataSource(); -class EmployeeDataSource extends DataGridSource { - EmployeeDataSource() { - buildDataGridRows(); - } +@override +void initState() { + super.initState(); + _employeeDataSource.buildDataGridRows(_employees); +} + +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Syncfusion Flutter DataGrid'), + ), + body: Column(children: [ + TextButton( + child: const Text('Update cell value'), + onPressed: () { + _employees[0].salary = 25000; + _employeeDataSource.dataGridRows[0] = DataGridRow(cells: [ + DataGridCell(value: _employees[0].id, columnName: 'id'), + DataGridCell(value: _employees[0].name, columnName: 'name'), + DataGridCell( + value: _employees[0].designation, + columnName: 'designation'), + DataGridCell(value: _employees[0].salary, columnName: 'salary'), + ]); + _employeeDataSource.updateDataGridSource( + rowColumnIndex: RowColumnIndex(0, 3)); + }), + SfDataGrid(source: _employeeDataSource, columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ))) + ]) + ])); +} - void buildDataGridRows() { - dataGridRows = _employees +class EmployeeDataSource extends DataGridSource { + void buildDataGridRows(List employees) { + dataGridRows = employees .map((dataGridRow) => DataGridRow(cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), @@ -358,10 +404,16 @@ class EmployeeDataSource extends DataGridSource { }).toList()); } - void updateDataGridSource({required RowColumnIndex rowColumnIndex}) { - notifyDataSourceListeners(rowColumnIndex: rowColumnIndex); + void updateDataGridSource({RowColumnIndex? rowColumnIndex}) { + if (rowColumnIndex != null) { + notifyDataSourceListeners(rowColumnIndex: rowColumnIndex); + } else { + notifyListeners(); + } } } {% endhighlight %} {% endtabs %} + +N> Use `notifyDataSourceListeners` with a specific `RowColumnIndex` for better performance when updating individual cells. Use `notifyListeners` only when the entire row or multiple cells need to be refreshed. diff --git a/Flutter/datagrid/editing.md b/Flutter/datagrid/editing.md index 388d1e87c..0bea1475f 100644 --- a/Flutter/datagrid/editing.md +++ b/Flutter/datagrid/editing.md @@ -11,6 +11,12 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) supports editing the cell values by setting the [SfDataGrid.allowEditing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowEditing.html) property to true, [SfDataGrid.navigationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) to cell, and [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) to a value other than none. +>**NOTE** + **Requirements**: Flutter 2.0 or later, `syncfusion_flutter_datagrid` package (latest version recommended). The `collection` package is required for the `firstWhereOrNull` helper method used in examples. + +>**NOTE** + The editing feature requires the `syncfusion_flutter_datagrid` package. Ensure you have added it to your `pubspec.yaml` file and imported it in your code. + By default, the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) does not load any widget when a cell enters edit mode. You must provide the required widget when a cell enters edit mode by returning it through the [DataGridSource.buildEditWidget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildEditWidget.html) method in the [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/DataGridSource.html) class. The following arguments are passed in the `buildEditWidget` method. @@ -20,13 +26,20 @@ The following arguments are passed in the `buildEditWidget` method. * [column](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html): Gets the Grid Column of the SfDataGrid. * [submitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/CellSubmit.html): Programmatically call to end the editing. Typically, this method can be called when the widget completes its editing. For example, `TextField.onSubmitted` method is called whenever TextField ends its editing. So, you can simply call submitCell method. This will automatically call the DataGridSource. -It is recommended to save the edited value through editors in the [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method. The `onCellSubmit` method will be called whenever the [submitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/CellSubmit.html) method from the [buildEditWidget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildEditWidget.html) method is called, or when other cells are navigated while a cell is in edit mode. +We recommend saving the edited value through the editor widgets in the [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method. The `onCellSubmit` method will be called whenever the [submitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/CellSubmit.html) method from the [buildEditWidget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildEditWidget.html) method is called, or when other cells are navigated while a cell is in edit mode. The following example shows how to enable editing in Datagrid and commit the edited cell value in the `onCellSubmit` method. +>**NOTE** + The `firstWhereOrNull` method is from the [collection](https://pub.dev/packages/collection) package. Add it to your `pubspec.yaml` dependencies and import with `import 'package:collection/collection.dart';` + {% tabs %} {% highlight dart %} +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:collection/collection.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -86,14 +99,18 @@ The following example shows how to enable editing in Datagrid and commit the edi } class EmployeeDataSource extends DataGridSource { - /// Helps to hold the new value of all editable widgets. - /// Based on the new value we will commit the new value into the corresponding - /// DataGridCell on the onCellSubmit method. + /// Holds the underlying data for the DataGrid + late List _employees; + + /// Stores the new value of the edited cell dynamic newCellValue; - /// Helps to control the editable text in the [TextField] widget. + /// Controls the editable text in the [TextField] widget TextEditingController editingController = TextEditingController(); + /// List to store DataGridRow objects + late List dataGridRows; + @override Future onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async { @@ -186,6 +203,9 @@ class EmployeeDataSource extends DataGridSource { ![flutter datagrid editing](images/editing/datagrid_editing.gif) +>**NOTE** + The `TextEditingController` used in the example should be disposed to free up resources. Consider implementing disposal in your State class: `@override void dispose() { editingController.dispose(); super.dispose(); }` + >**NOTE** Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). @@ -260,8 +280,17 @@ To disable the editing for a particular column, set the [GridColumn.allowEditing ![flutter datagrid disable the editing for specific column](images/editing/disable_editing.gif) +>**NOTE** + Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). + ## Entering edit mode +The [SfDataGrid.editingGestureType](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/editingGestureType.html) property controls how a cell enters edit mode. The available options are: + +* **doubleTap**: Cell enters edit mode on double-tap (default behavior) +* **tap**: Cell enters edit mode on single tap +* **longPress**: Cell enters edit mode on long press + By default, a cell will enter edit mode when you double-tap it. To enable editing with a single tap, set the [SfDataGrid.editingGestureType](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/editingGestureType.html) property to tap. {% tabs %} @@ -331,9 +360,12 @@ By default, a cell will enter edit mode when you double-tap it. To enable editin ## Methods +>**NOTE** + The editing lifecycle consists of three key methods: `onCellBeginEdit` (called when entering edit mode), `canSubmitCell` (called before exiting edit mode for validation), and `onCellSubmit` (called when changes are confirmed). All methods are asynchronous-capable. + ### onCellBeginEdit -The [DataGridSource.onCellBeginEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellBeginEdit.html) method is called when a cell enters edit mode. Return false if you don’t want specific cells to enter edit mode. The following arguments are passed in this method: +The [DataGridSource.onCellBeginEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellBeginEdit.html) method is called when a cell enters edit mode. This is a synchronous method where you can prevent specific cells from entering edit mode by returning `false`. The following arguments are passed in this method: * [row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRow-class.html): Gets the DataGridRow of the SfDataGrid. * [rowColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowColumnIndex-class.html): Gets the current row and column index of the DataGrid. @@ -360,7 +392,7 @@ class EmployeeDataSource extends DataGridSource { ### canSubmitCell -The [DataGridSource.canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) is called before the cell is ending its editing. If you want to restrict the cell from being end its editing, you can return false. [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) will be called only if the `canSubmitCell` returns true. The following arguments are passed in this method, +The [DataGridSource.canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) method is called before the cell exits edit mode. This is an asynchronous method used for validating the edited value. If validation fails, return `false` to retain the cell in edit mode. The [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method will only be called if `canSubmitCell` returns `true`. The following arguments are passed in this method: * [row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRow-class.html): Gets the DataGridRow of the SfDataGrid. * [rowColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowColumnIndex-class.html): Gets the current row and column index of the DataGrid. @@ -372,23 +404,30 @@ The [DataGridSource.canSubmitCell](https://pub.dev/documentation/syncfusion_flut class EmployeeDataSource extends DataGridSource { @override Future canSubmitCell(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, - GridColumn column) { + GridColumn column) async { if (column.columnName == 'id' && newCellValue == null) { - // Return false, to retain in edit mode. - // To avoid null value for cell + // Return false to retain in edit mode and prevent null values return false; - } else { - return true; + } + if (column.columnName == 'salary' && newCellValue is int) { + // Validate salary value is within acceptable range + if (newCellValue < 0 || newCellValue > 1000000) { + return false; // Invalid salary, retain edit mode + } } + return true; } } {% endhighlight %} {% endtabs %} +>**NOTE** + To display validation error messages to users, consider showing a snackbar or dialog in the `canSubmitCell` method when returning `false`, or use a validation field overlay on the edit widget in `buildEditWidget`. + ### onCellSubmit -The [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method is called when the editing is completed. You are recommended to save the edited values to the underlying collection in this method. It makes sense to handle the entire editing operation in this single method. +The [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method is called when the editing is completed and validation passes. This is an asynchronous method where you should save the edited values to your underlying data collection. The UI automatically refreshes after changes are committed. >**NOTE** There is no need to call the `notifyListeners` after you update the DataGridRows. DataGrid will refresh the UI automatically. @@ -438,10 +477,10 @@ class EmployeeDataSource extends DataGridSource { ### onCellCancelEdit -The [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) method is called when you press the `Esc` key from Web and Desktop platforms. The [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) and [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) will not be called when the `Esc` key is pressed. +The [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) method is called when editing is cancelled. This occurs when the `Esc` key is pressed on Web and Desktop platforms. When this method is called, the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) and [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) methods are not called. Focus returns to the DataGrid after cancellation. >**NOTE** - No need to call the notifyListener inside it. + You do not need to call `notifyListeners` inside this method as the UI automatically handles state updates. {% tabs %} {% highlight dart %} @@ -544,6 +583,9 @@ The SfDataGrid allows moving the cell into edit mode programmatically by calling ![flutter datagrid begin edit](images/editing/begin_editing.gif) +>**NOTE** + Download the complete programmatic editing demo from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). + ### EndEdit The [SfDataGrid.endEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/endEdit.html) method can be called to programmatically end the editing for a specific cell. @@ -629,7 +671,7 @@ The [SfDataGrid.endEdit](https://pub.dev/documentation/syncfusion_flutter_datagr ## How to check whether the current cell is in editing mode -You can check whether the current cell is in editing mode by using the [DataGridController.isCurrentCellInEditing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/isCurrentCellInEditing.html) property. +You can check whether the current cell is in editing mode by using the [DataGridController.isCurrentCellInEditing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/isCurrentCellInEditing.html) property. This read-only boolean property returns `true` if a cell is currently in edit mode, and `false` otherwise. {% tabs %} {% highlight dart %} @@ -721,9 +763,9 @@ You can check whether the current cell is in editing mode by using the [DataGrid {% endhighlight %} {% endtabs %} -## Restrict specific cell or column from being entered into edit mode at run time +## Prevent editing for specific cells or columns -To cancel the editing for a specific cell or column at run time, override the [onCellBeginEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellBeginEdit.html) method in the `DataGridSource` class and return false for a specific cell or column. +To prevent editing for specific cells or columns at runtime, override the [onCellBeginEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellBeginEdit.html) method in the `DataGridSource` class and return `false` for the cells or columns you want to protect. {% tabs %} {% highlight dart %} @@ -767,9 +809,7 @@ class EmployeeDataSource extends DataGridSource { ## Cancel edited cell value from being committed -You can override the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) from the [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) class and return false based on your criteria. - -If you return a false from the `canSubmitCell` method, the Datagrid doesn't allow focus to move to other widgets outside the DataGrid. The focus will remain on the `currentCell`. +You can override the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) method from the [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) class and return `false` based on your validation criteria. When `canSubmitCell` returns `false`, the edited cell retains focus and edit mode, preventing the user from navigating away until the input is corrected. {% tabs %} {% highlight dart %} @@ -794,15 +834,18 @@ class EmployeeDataSource extends DataGridSource { ## Perform editing asynchronously -Editing can be performed asynchronously by handling the [DataGridSource.canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) method, which is called before the cell ends its editing and [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html), which is called when the cell ends its editing. +Editing can be performed asynchronously by implementing the [DataGridSource.canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) method for validation and [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method for saving data. Both methods support `async` operations, allowing you to perform network requests or database operations. -The following example shows how to display a loading indicator for a specific amount of time when the cell ends its editing and also shows the loading indicator until the cell validates whether the entered value is valid. +The following example shows how to display a loading indicator during asynchronous validation and data persistence operations: {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'dart:async'; +/// Global StreamController to manage loading state during async operations StreamController loadingController = StreamController(); List employees = []; @@ -917,14 +960,19 @@ class _MyHomePageState extends State { Future canSubmitCell(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async { if (column.columnName == 'id' && newCellValue == 104) { + // Show loading indicator during validation loadingController.add(true); + // Simulate server-side validation await Future.delayed(const Duration(seconds: 2)); loadingController.add(false); - return false; + return false; // Reject this specific value } else { - return true; + return true; // Allow submission for other values } } {% endhighlight %} {% endtabs %} + +>**NOTE** + The `StreamController` pattern is used here to manage UI state during async operations. The loading indicator is shown/hidden by emitting values to the stream. You can also use state management solutions like `Provider`, `Riverpod`, or `Bloc` for more complex scenarios. diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index 3fbe43daf..81a8171f8 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -19,19 +19,22 @@ The following dependencies must be added to your pubspec.yaml file for exporting dependencies: +syncfusion_flutter_datagrid: ^xx.x.xx syncfusion_flutter_datagrid_export: ^xx.x.xx +syncfusion_flutter_xlsio: ^xx.x.xx {% endhighlight %} ->**NOTE:** Here, **xx.x.xx** denotes the current version of `Syncfusion Flutter DataGrid Export` package. +>**NOTE:** Replace **xx.x.xx** with the latest version of the packages from [pub.dev](https://pub.dev). Ensure all three packages have compatible versions. Requires Flutter 3.0 and above. **Import package** -Import the following package in your Dart code. +Import the following packages in your Dart code. {% tabs %} {% highlight Dart %} +import 'dart:io'; import 'package:syncfusion_flutter_datagrid_export/export.dart'; import 'package:syncfusion_flutter_xlsio/xlsio.dart'; @@ -44,9 +47,34 @@ Export the `SfDataGrid` by using the following extension methods present in the * [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) +**Create a helper method for saving files** + +Create a helper method to save and launch the exported Excel file. This method handles platform-specific file operations. + +{% tabs %} +{% highlight Dart %} + +class FileHelper { + static Future saveAndLaunchFile(List bytes, String fileName) async { + final String path = (await getApplicationDocumentsDirectory()).path; + final File file = File('$path/$fileName'); + await file.writeAsBytes(bytes, flush: true); + + if (await file.exists()) { + // Open the file with the default application + await OpenFile.open('$path/$fileName'); + } + } +} + +{% endhighlight %} +{% endtabs %} + +>**NOTE:** You need to add the `path_provider` and `open_file` packages to your pubspec.yaml to use the helper method above. + **Add GlobalKey for the DataGrid** -Create the [GlobalKey](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) using the `SfDataGridState` class. Exporting related methods are available in the `SfDataGridState` class. +Create the [GlobalKey](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) using the `SfDataGridState` class. Exporting related methods are available in the [SfDataGridState](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html) class. Set the created `GlobalKey` to the `SfDataGrid`. @@ -63,7 +91,7 @@ The following code illustrates how to create and export a `SfDataGrid` to Excel {% tabs %} {% highlight Dart %} -final GlobalKey key = GlobalKey(); +final GlobalKey _dataGridKey = GlobalKey(); @override Widget build(BuildContext context) { @@ -90,15 +118,15 @@ Widget build(BuildContext context) { )), onPressed: () async { final Workbook workbook = - key.currentState!.exportToExcelWorkbook(); + _dataGridKey.currentState!.exportToExcelWorkbook(); final List bytes = workbook.saveAsStream(); workbook.dispose(); - await helper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); + await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); }), ), Expanded( child: SfDataGrid( - key: key, + key: _dataGridKey, source: employeeDataSource, columns: [ GridColumn( @@ -141,36 +169,36 @@ Widget build(BuildContext context) { {% endhighlight %} {% endtabs %} -## Save the Excel document as a file -To save the file as an Excel document, it’s necessary to include [mobile](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-mobile), [web](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-web) and [desktop](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-desktop) platform-specific file generating code. ## Export DataGrid to Excel workbook -You can export the data to [Excel Workbook](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Workbook-class.html) by using the `exportToExcelWorkbook` method from the `key.currentState` of the DataGrid. +You can export the data to an [Excel Workbook](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Workbook-class.html) by using the [exportToExcelWorkbook](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorkbook.html) method from the `currentState` of the DataGrid. {% tabs %} {% highlight Dart %} -final Workbook workbook = key.currentState!.exportToExcelWorkbook(); +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook(); final List bytes = workbook.saveAsStream(); -File('DataGrid.xlsx').writeAsBytes(bytes, flush: true); +workbook.dispose(); +await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); {% endhighlight %} {% endtabs %} ## Export DataGrid to Excel sheet -Export the data to [Excel Worksheet](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Worksheet-class.html) by using the `exportToExcelWorksheet` method from the `key.currentState` of the DataGrid. +Export the data to an [Excel Worksheet](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Worksheet-class.html) by using the [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) method from the `currentState` of the DataGrid. {% tabs %} {% highlight Dart %} final Workbook workbook = Workbook(); final Worksheet worksheet = workbook.worksheets[0]; -key.currentState!.exportToExcelWorksheet(worksheet); +_dataGridKey.currentState!.exportToExcelWorksheet(worksheet); final List bytes = workbook.saveAsStream(); -File('DataGrid.xlsx').writeAsBytes(bytes, flush: true); +workbook.dispose(); +await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); {% endhighlight %} {% endtabs %} @@ -184,9 +212,10 @@ By default, all the columns in the `SfDataGrid` are exported to Excel. To exclud {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState! +final Workbook workbook = _dataGridKey.currentState! .exportToExcelWorkbook(excludeColumns: ['Name']); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -200,9 +229,10 @@ By default, table summaries in the `SfDataGrid` are exported to Excel. Set the [ {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState! +final Workbook workbook = _dataGridKey.currentState! .exportToExcelWorkbook(exportTableSummaries: false); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -214,9 +244,10 @@ By default, stacked headers in the `SfDataGrid` are exported to Excel. Set the [ {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState! +final Workbook workbook = _dataGridKey.currentState! .exportToExcelWorkbook(exportStackedHeaders: false); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -228,54 +259,74 @@ By default, the DataGrid is exported from the (0,0) index in an Excel sheet. Exp {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState! +final Workbook workbook = _dataGridKey.currentState! .exportToExcelWorkbook(startRowIndex: 3, startColumnIndex: 2); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} ## Export the selected rows to Excel -By default, the entire grid is exported to Excel. Export the selected rows only by passing the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) to [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToExcelWorksheet` and `exportToExcelWorkbook` methods. +By default, the entire grid is exported to Excel. Export the selected rows only by passing the [selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) from the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) to the [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToExcelWorksheet` and `exportToExcelWorkbook` methods. {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState! - .exportToExcelWorkbook(rows: dataGridController.selectedRows); +final DataGridController controller = DataGridController(); + +// In your SfDataGrid widget +SfDataGrid( + controller: controller, + // ... other properties +); + +// Export selected rows +final Workbook workbook = _dataGridKey.currentState! + .exportToExcelWorkbook(rows: controller.selectedRows); final List bytes = workbook.saveAsStream(); +workbook.dispose(); +await FileHelper.saveAndLaunchFile(bytes, 'SelectedRows.xlsx'); {% endhighlight %} {% endtabs %} +>**NOTE:** Ensure row selection is enabled in the SfDataGrid by setting the `selectionMode` property to `SelectionMode.multiple` or `SelectionMode.single`. + ## Row height and column width customization -By default, [SfDataGrid.rowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowHeight.html) and [SfDataGrid.defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/defaultColumnWidth.html) properties will be set to the cells in the Excel sheet. To customize the row height and column width in Excel, you can use the [defaultRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultRowHeight.html) and [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultColumnWidth.html) properties. But these properties are only applicable when the [exportRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportRowHeight.html) and [exportColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportColumnWidth.html) properties are `false`. +The following table explains how row height and column width are handled during export: + +| Property | When `true` | When `false` | +|----------|-----------|-----------| +| [exportRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportRowHeight.html) | Uses `SfDataGrid.headerRowHeight` and `SfDataGrid.rowHeight` from the DataGrid | Uses [defaultRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultRowHeight.html) value | +| [exportColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportColumnWidth.html) | Uses actual column widths from the DataGrid | Uses [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultColumnWidth.html) value | -If the `exportRowHeight` and `exportColumnWidth` properties are `true`, the [SfDataGrid.headerRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerRowHeight.html) and `SfDataGrid.rowHeight` properties are considered for row heights in Excel and the actual width of the column is considered for columns in Excel. +**Example: Use custom row height and column width** {% tabs %} {% highlight Dart %} -Workbook workbook = key.currentState!.exportToExcelWorkbook( +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( exportRowHeight: false, exportColumnWidth: false, defaultRowHeight: 35, defaultColumnWidth: 120); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} ## Styling cells based on the cell type in Excel -Customize the cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) parameter, which is a callback in the `exportToExcelWorkbook` and `exportToExcelWorksheet` methods. +Customize the cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback parameter in the `exportToExcelWorkbook` and `exportToExcelWorksheet` methods. {% tabs %} {% highlight Dart %} -final Workbook workbook = key.currentState!.exportToExcelWorkbook( +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.columnHeader) { details.excelRange.cellStyle.backColor = '#42A5F5'; @@ -284,6 +335,7 @@ final Workbook workbook = key.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -294,12 +346,12 @@ final List bytes = workbook.saveAsStream(); ### Customize cell values while exporting -The cell value can be customized while exporting to Excel by directly setting the cell value to the [excelRange.value](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails/excelRange.html) property available in the argument of `cellExport` callback. +The cell value can be customized while exporting to Excel by directly setting the cell value to the [excelRange.value](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails/excelRange.html) property available in the argument of the `cellExport` callback. {% tabs %} {% highlight Dart %} -final Workbook workbook = key.currentState!.exportToExcelWorkbook( +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.row && details.cellValue == 'Project Lead') { @@ -307,6 +359,7 @@ final Workbook workbook = key.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -315,12 +368,12 @@ final List bytes = workbook.saveAsStream(); ### Customize the cells based on the column -You can customize the column style based on the column name when exporting to Excel by using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) parameter. +You can customize the column style based on the column name when exporting to Excel by using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback parameter. {% tabs %} {% highlight Dart %} -final Workbook workbook = key.currentState!.exportToExcelWorkbook( +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.row && details.columnName == 'Name') { @@ -330,6 +383,7 @@ final Workbook workbook = key.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); +workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -338,82 +392,52 @@ final List bytes = workbook.saveAsStream(); Customize the exporting behavior by overriding the available methods in the [DataGridToExcelConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter-class.html) class. Use the `converter` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` method. +**Example: Customize column headers and apply formatting** + {% tabs %} {% highlight Dart %} class CustomDataGridToExcelConverter extends DataGridToExcelConverter { - @override - void exportColumnHeader(SfDataGrid dataGrid, GridColumn column, - String columnName, Worksheet worksheet) { - // TODO: Add your requirements in exportColumnHeader - super.exportColumnHeader(dataGrid, column, columnName, worksheet); - } - @override void exportColumnHeaders(SfDataGrid dataGrid, Worksheet worksheet) { - // TODO: Add your requirements in exportColumnHeaders + // Apply custom formatting to headers super.exportColumnHeaders(dataGrid, worksheet); + final Range headerRange = worksheet.getRangeByIndex(1, 1, 1, dataGrid.columns.length); + headerRange.cellStyle.bold = true; + headerRange.cellStyle.fontSize = 12; } @override - void exportRow(SfDataGrid dataGrid, DataGridRow row, GridColumn column, - Worksheet worksheet) { - // TODO: Add your requirements in exportRow - super.exportRow(dataGrid, row, column, worksheet); - } - - @override - void exportRows( - SfDataGrid dataGrid, List rows, Worksheet worksheet) { - // TODO: Add your requirements in exportRows - super.exportRows(dataGrid, rows, worksheet); - } - - @override - void exportStackedHeaderRow(SfDataGrid dataGrid, - StackedHeaderRow stackedHeaderRow, Worksheet worksheet) { - // TODO: Add your requirements in exportStackedHeaderRow - super.exportStackedHeaderRow(dataGrid, stackedHeaderRow, worksheet); - } - - @override - void exportStackedHeaderRows(SfDataGrid dataGrid, Worksheet worksheet) { - // TODO: Add your requirements in exportStackedHeaderRows - super.exportStackedHeaderRows(dataGrid, worksheet); - } - - @override - void exportTableSummaryRow(SfDataGrid dataGrid, - GridTableSummaryRow summaryRow, Worksheet worksheet) { - // TODO: Add your requirements in exportTableSummaryRow - super.exportTableSummaryRow(dataGrid, summaryRow, worksheet); + Object? getCellValue(DataGridRow row, GridColumn column) { + // Customize cell values during export + final Object? cellValue = super.getCellValue(row, column); + if (column.columnName == 'Salary' && cellValue != null) { + return '\$$cellValue'; // Format salary with currency symbol + } + return cellValue; } @override void exportTableSummaryRows(SfDataGrid dataGrid, GridTableSummaryRowPosition position, Worksheet worksheet) { - // TODO: Add your requirements in exportTableSummaryRows + // Add custom handling for summary rows super.exportTableSummaryRows(dataGrid, position, worksheet); } - - @override - Object? getCellValue(DataGridRow row, GridColumn column) { - // TODO: Add your requirements in getCellValue - super.getCellValue(row, column); - } } {% endhighlight %} {% endtabs %} -The following code sample illustrates how to create an instance of the `CustomDataGridToExcelConverter` class and set the instance to the `converter` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` method. +**Use the custom converter when exporting** {% tabs %} {% highlight Dart %} -CustomDataGridToExcelConverter converter = CustomDataGridToExcelConverter(); -Workbook workbook = key.currentState!.exportToExcelWorkbook(converter: converter); +final CustomDataGridToExcelConverter converter = CustomDataGridToExcelConverter(); +final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook(converter: converter); final List bytes = workbook.saveAsStream(); +workbook.dispose(); +await FileHelper.saveAndLaunchFile(bytes, 'CustomExport.xlsx'); {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index ad5bf1a36..d19b9b723 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -18,29 +18,29 @@ The following dependencies must be added to your `pubspec.yaml` file for exporti {% highlight dart %} dependencies: - -syncfusion_flutter_datagrid_export: ^xx.x.xx + syncfusion_flutter_datagrid_export: ^24.1.41 + syncfusion_flutter_pdf: ^24.1.41 {% endhighlight %} - >**NOTE** Here, **xx.x.xx** denotes the current version of `Syncfusion® Flutter DataGrid Export` package. +>**NOTE** Ensure that you have the latest version of the `syncfusion_flutter_datagrid_export` and `syncfusion_flutter_pdf` packages. For the latest available versions, refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export). **Import package** -Import the following package in your Dart code. +Import the following packages in your Dart code. {% tabs %} {% highlight Dart %} +import 'dart:io'; import 'package:syncfusion_flutter_datagrid_export/export.dart'; - import 'package:syncfusion_flutter_pdf/pdf.dart'; {% endhighlight %} {% endtabs %} -You can export the `SfDataGrid` to PDF by using the following extension methods present in the [SfDataGridState]((https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html)) class: +You can export the `SfDataGrid` to PDF by using the following extension methods present in the [SfDataGridState](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html) class: * [exportToPdfDocument](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfDocument.html) * [exportToPdfGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfGrid.html) @@ -54,87 +54,97 @@ Set the created `GlobalKey` to the `SfDataGrid`. {% tabs %} {% highlight Dart %} - final GlobalKey key = GlobalKey(); +final GlobalKey key = GlobalKey(); {% endhighlight %} {% endtabs %} +>**NOTE** The `_employeeDataSource` used in the examples should be a [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) implementation containing your data model. Ensure that your data model includes properties like 'ID', 'Name', 'Designation', and 'Salary' as shown in the columns. + The following code illustrates how to create and display a `SfDataGrid` using the global key. {% tabs %} {% highlight Dart %} - GlobalKey key = GlobalKey(); - - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - ElevatedButton( - child: Text('Export To Pdf'), - onPressed: () { - PdfDocument document = key.currentState!.exportToPdfDocument() - final List bytes = document.saveSync(); - }), - Expanded( - child: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - ), +GlobalKey key = GlobalKey(); + +@override +Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + ElevatedButton( + child: Text('Export To PDF'), + onPressed: () { + PdfDocument document = key.currentState!.exportToPdfDocument(); + final List bytes = document.saveSync(); + File('DataGrid.pdf').writeAsBytes(bytes); + }), + Expanded( + child: SfDataGrid( + key: key, + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'ID', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ))), + ], ), - ], - ), - ); - } + ), + ], + ), + ); +} {% endhighlight %} {% endtabs %} ## Save the PDF document as a file -To save the file as a PDF document, it’s necessary to include [mobile](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile), [web](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) and desktop platform-specific file generating code. +To save the exported PDF file, include platform-specific file generating code based on your target platform: + +- **Mobile (iOS/Android)**: Refer to [Save and open a PDF document in mobile](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) +- **Web**: Refer to [Save and download a PDF document in web](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) +- **Desktop (Windows/macOS/Linux)**: Use the `File` class from the `dart:io` package to write bytes to a file + +>**NOTE** The `File` class requires the `dart:io` package, which is already included in your imports from the previous section. ## Export DataGrid to PDF document -Export the data to the [PdfDocument](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocument-class.html) by using the `exportToPdfDocument` method from the `key.currentState` of the DataGrid. +Use the [exportToPdfDocument](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfDocument.html) method to export the data to a [PdfDocument](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocument-class.html). {% tabs %} {% highlight Dart %} @@ -148,7 +158,9 @@ File('DataGrid.pdf').writeAsBytes(bytes); ## Export DataGrid to PDF Grid -Export the data to the [PdfGrid](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfGrid-class.html) by using the `exportToPdfGrid` method from the `key.currentState` of the DataGrid. +Use the [exportToPdfGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfGrid.html) method to export the data to a [PdfGrid](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfGrid-class.html). This method is useful when you need more control over page settings or when combining the grid with other content. + +>**NOTE** The `exportToPdfGrid` method returns a `PdfGrid` that can be drawn onto a `PdfPage`, allowing for customization of page orientation, margins, and other page-level settings. {% tabs %} {% highlight Dart %} @@ -166,11 +178,26 @@ File('DataGrid.pdf').writeAsBytes(bytes); {% endhighlight %} {% endtabs %} -## Exporting options +## Exporting options + +The following table summarizes the available export options and their use cases: + +| Parameter | Type | Default | Description | +|-----------|------|---------|-------------| +| `excludeColumns` | List | - | Columns to exclude from the export | +| `canRepeatHeaders` | bool | true | Repeat column headers on each page | +| `fitAllColumnsInOnePage` | bool | false | Fit all columns on a single page | +| `exportTableSummaries` | bool | true | Include table summaries in export | +| `exportStackedHeaders` | bool | true | Include stacked headers in export | +| `autoColumnWidth` | bool | true | Automatically size column widths | +| `rows` | List | null | Specific rows to export (null = all rows) | +| `cellExport` | Function | null | Callback for cell customization | +| `headerFooterExport` | Function | null | Callback for header/footer customization | +| `converter` | DataGridToPdfConverter | null | Custom converter class for advanced customization | ### Exclude columns when exporting -By default, all the columns in the SfDataGrid are exported to PDF. To exclude some particular columns while exporting to PDF, add those column names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter-class.html) parameter. +By default, all columns in the SfDataGrid are exported to PDF. To exclude specific columns, add the column names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/excludeColumns.html) parameter. {% tabs %} {% highlight Dart %} @@ -198,7 +225,7 @@ final List bytes = document.saveSync(); ### Export all columns on one page -Fit all the columns on one page by setting the [fitAllColumnsInOnePage](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/fitAllColumnsInOnePage.html) parameter as `true.` +Fit all columns on a single page by setting the [fitAllColumnsInOnePage](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/fitAllColumnsInOnePage.html) parameter to `true`. {% tabs %} {% highlight Dart %} @@ -238,7 +265,7 @@ final List bytes = document.saveSync(); ### Auto-size column widths in PDF -In order, to export the actual column width from `SfDataGrid` instead of the auto column width, set the [autoColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/autoColumnWidth.html) parameter as `false`. +To export the actual column width from `SfDataGrid` instead of auto-sizing, set the [autoColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/autoColumnWidth.html) parameter to `false`. {% tabs %} {% highlight Dart %} @@ -249,8 +276,7 @@ final List bytes = document.saveSync(); {% endhighlight %} {% endtabs %} ->**NOTE** - If you disabled the `autoColumnWidth`, then you must set `fitAllColumnsInOnePage` as false. Then only, the overflowing columns are drawn in next page. Because `fitAllColumnsInOnePage` has topmost priority. +>**NOTE** If you disable `autoColumnWidth`, you must set `fitAllColumnsInOnePage` to `false`. In this configuration, overflowing columns will be drawn on the next page. The `fitAllColumnsInOnePage` parameter takes precedence over `autoColumnWidth`. ## Change the orientation of the PDF document @@ -276,12 +302,14 @@ final List bytes = document.saveSync(); ## Export the selected rows to PDF -By default, the entire grid is exported to PDF. Export the selected rows only by passing the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) to [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToPdfDocument` and `exportToPdfGrid` methods. +By default, the entire grid is exported to PDF. To export only selected rows, pass the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) to the [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. + +>**NOTE** Ensure that the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) is assigned to the SfDataGrid using the `controller` property and that row selection is enabled by setting `selectionMode` to an appropriate value (e.g., `SelectionMode.single` or `SelectionMode.multiple`). {% tabs %} {% highlight Dart %} -PdfDocument document = key.currentState!.exportToPdfDocument(rows: dataGridController.selectedRows,); +PdfDocument document = key.currentState!.exportToPdfDocument(rows: dataGridController.selectedRows); final List bytes = document.saveSync(); {% endhighlight %} @@ -318,7 +346,7 @@ final List bytes = document.saveSync(); ## Styling cells based on the cell type in PDF -You can customize the cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/cellExport.html) parameter, which is a callback in `exportToPdfDocument` or `exportToPdfGrid` methods. +Customize cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/cellExport.html) callback parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. The [DataGridExportCellType](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExportCellType.html) enum provides the following cell types: `columnHeader`, `row`, `stackedHeaderRow`, and `tableSummaryRow`. {% tabs %} {% highlight Dart %} @@ -326,9 +354,12 @@ You can customize the cell styles based on cell type using the [cellExport](http PdfDocument document = key.currentState!.exportToPdfDocument(cellExport: (details) { if (details.cellType == DataGridExportCellType.columnHeader) { details.pdfCell.style.backgroundBrush = PdfBrushes.pink; - } - if (details.cellType == DataGridExportCellType.row) { + } else if (details.cellType == DataGridExportCellType.row) { details.pdfCell.style.backgroundBrush = PdfBrushes.lightCyan; + } else if (details.cellType == DataGridExportCellType.stackedHeaderRow) { + details.pdfCell.style.backgroundBrush = PdfBrushes.lightGray; + } else if (details.cellType == DataGridExportCellType.tableSummaryRow) { + details.pdfCell.style.backgroundBrush = PdfBrushes.wheat; } }); final List bytes = document.saveSync(); @@ -342,7 +373,7 @@ final List bytes = document.saveSync(); ### Customize cell values while exporting -The cell value can be customized while exporting to PDF by directly setting the cell value of a cell in the `PdfGrid` via the [PdfCell](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails/pdfCell.html) property available in the argument of the `cellExport` callback. +Customize cell values during export by setting the [PdfCell](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails/pdfCell.html) value property in the `cellExport` callback. The [DataGridCellPdfExportDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails-class.html) provides cell information including `cellValue`, `columnName`, and `rowIndex`. {% tabs %} {% highlight Dart %} @@ -362,27 +393,27 @@ final List bytes = document.saveSync(); ![pdf document shows the cell customization](images/export-to-pdf/flutter-datagrid-pdf-cell-customization.png) -### Customize the Cells based on Column Name +### Customize cells based on column name -You can customize the column style based on the column name while exporting to PDF by using the `cellExport` parameter. +Customize cell styles based on the column name using the `cellExport` callback parameter. {% tabs %} {% highlight Dart %} PdfDocument document = key.currentState!.exportToPdfDocument(cellExport: (details) { - if (details.cellType == DataGridExportCellType.row && details.columnName == 'Customer Name') { - details.pdfCell.style.textBrush = PdfBrushes.red; - } + if (details.cellType == DataGridExportCellType.row && + details.columnName == 'Customer Name') { + details.pdfCell.style.textBrush = PdfBrushes.red; } -); +}); final List bytes = document.saveSync(); {% endhighlight %} {% endtabs %} -## Customize Exporting Behavior +## Customize exporting behavior -Customize the exporting behavior by overriding the available methods in the [DataGridToPdfConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter-class.html) class. Use the `converter` parameter in the `exportToPdfDocument` or `exportToPdfGrid` method. +For advanced customization, override methods in the [DataGridToPdfConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter-class.html) class and use the `converter` parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. This allows you to control how column headers, rows, and data are processed during export. {% tabs %} {% highlight Dart %} @@ -391,31 +422,27 @@ class CustomDataGridToPdfConverter extends DataGridToPdfConverter { @override void exportColumnHeader(SfDataGrid dataGrid, GridColumn column, String columnName, PdfGrid pdfGrid) { - // TODO: Add your requirements column header - + // Add custom column header export logic here super.exportColumnHeader(dataGrid, column, columnName, pdfGrid); } @override void exportColumnHeaders( SfDataGrid dataGrid, List columns, PdfGrid pdfGrid) { - // TODO: Add your requirements column headers - + // Add custom column headers export logic here super.exportColumnHeaders(dataGrid, columns, pdfGrid); } @override void exportRows( List columns, List rows, PdfGrid pdfGrid) { - // TODO: Add your requirements in exportRows - + // Add custom rows export logic here super.exportRows(columns, rows, pdfGrid); } @override void exportRow(List columns, DataGridRow row, PdfGrid pdfGrid) { - // TODO: Add your requirements in exportRow - + // Add custom row export logic here super.exportRow(columns, row, pdfGrid); } } diff --git a/Flutter/datagrid/filtering.md b/Flutter/datagrid/filtering.md index aae9c7547..ae6fcc42c 100644 --- a/Flutter/datagrid/filtering.md +++ b/Flutter/datagrid/filtering.md @@ -9,12 +9,18 @@ documentation: ug # Filtering in Flutter DataGrid (SfDataGrid) -Filtering is the process of fetching the values from a collection that satisfy specified condition. In the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html), filtering can be applied both through the UI and programmatically. +Filtering is the process of fetching values from a collection that satisfy specified conditions. In the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html), filtering can be applied both through the UI and programmatically. + +> **NOTE** + This feature requires the `syncfusion_flutter_datagrid` package version 20.2.38 or later. Ensure that you have added the package to your `pubspec.yaml` file. ## Programmatic Filtering The SfDataGrid allows you to filter the data rows programmatically by adding filter conditions along with their respective column names to the [DataGridSource.filterConditions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/filterConditions.html) map collection. In the map collection, the `key` defines the [columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) and the `values` define the list of [FilterCondition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterCondition-class.html). +> **NOTE** + To use programmatic filtering, you must have a custom class that extends [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) with properly initialized data rows. + `DataGridSource.filterConditions` is an unmodifiable map collection. So, it doesn't allow us to perform CRUD operations directly in the `DataGridSource.filterConditions` property. However, it can be done by the following public methods: ### Add filter @@ -255,10 +261,10 @@ Filter conditions can be cleared from all columns using the [DataGridSource.clea ### Filter behavior -The [FilterBehavior](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterBehavior.html) property specifies whether filtering should consider cell values as strings or by their actual data types. +The [FilterBehavior](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterBehavior.html) property specifies whether filtering should consider cell values as strings or by their actual data types. This property is set in the [FilterCondition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterCondition-class.html) object. -* **stringDataType** - Converts the cell value to a string data type before comparing. -* **strongDataType** - Compares the cell value using its actual data type. +* **stringDataType** - Converts the cell value to a string data type before comparing. Use this for case-insensitive or partial text matching. +* **strongDataType** - Compares the cell value using its actual data type (e.g., numeric, DateTime). Use this for precise type-specific filtering. {% tabs %} {% highlight Dart %} @@ -527,12 +533,15 @@ After filtering, you can retrieve the rows in the same order as displayed in the ## UI Filtering -`SfDataGrid` provides an Excel-like filtering UI and an advanced filter UI for easy data filtering. UI filtering can be enabled by setting the [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) property to `true.` This allows the filter UI to be opened by clicking the filter icon in the column header. The filtering UI appears as a popup menu on desktop and web platforms, and as a new page on mobile platforms. +`SfDataGrid` provides an Excel-like filtering UI and an advanced filter UI for easy data filtering. UI filtering can be enabled by setting the [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) property to `true`. This allows the filter UI to be opened by clicking the filter icon in the column header. + +> **NOTE** + **Platform-specific behavior:** The filtering UI appears as a popup menu on desktop and web platforms, and as a new page on mobile platforms. -The `SfDataGrid` provides the following types of filter popup modes: +The `SfDataGrid` provides the following types of filter UI modes: -* **Checkbox Filter** - Provides excel like filter interface with a list of checkboxes. -* **Advanced Filter** - Provides advanced filter options to filter the data with multiple conditions. +* **Checkbox Filter** - Provides an Excel-like filter interface with a list of checkboxes for selecting specific values. +* **Advanced Filter** - Provides advanced filter options to filter data with multiple conditions using filter types and operators. The following image shows the checkbox filter popup menu on the web and desktop platforms, @@ -599,9 +608,9 @@ The following image shows the filtered data rows which are filtered by the advan Flutter datagrid shows the filtered rows -#### Case sensitive filtering +#### Case-sensitive filtering -Case-sensitive filtering can be enabled for the column using the casing icon available in the advanced filter UI. This is available only for the `TextFilters` filter view. If the icon is active, the filtering will be applied with the case sensitive with the filter text. The case-sensitive icon will be shown only to the string-type columns. +Case-sensitive filtering can be enabled for the column using the case-sensitive icon available in the advanced filter UI. This option is available only for text-based columns. When enabled, the filter comparison will be case-sensitive with respect to the filter text. The following image shows the advanced filter popup menu with a case-sensitive icon, @@ -609,16 +618,19 @@ The following image shows the advanced filter popup menu with a case-sensitive i ### Disable filtering for an individual column -The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/allowFiltering.html) has a higher priority than the `SfDataGrid.allowFiltering` property. So, you can disable the filtering for any particular column by setting the `GridColumn.allowFiltering` property to `false`. +The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/allowFiltering.html) property has a higher priority than the `SfDataGrid.allowFiltering` property. Disable filtering for any particular column by setting the `GridColumn.allowFiltering` property to `false`. {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + @override Widget build(BuildContext context) { return SfDataGrid( allowFiltering: true, - source: _employeeDataSource, + source: employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, columns: [ GridColumn( allowFiltering: false, @@ -629,8 +641,8 @@ The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter child: Text( 'ID', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Name', @@ -640,8 +652,8 @@ The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter child: Text( 'Name', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Designation', @@ -651,8 +663,8 @@ The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter child: Text( 'Designation', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Salary', @@ -662,38 +674,42 @@ The [GridColumn.allowFiltering](https://pub.dev/documentation/syncfusion_flutter child: Text( 'Salary', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), - ] + ], ); } {% endhighlight %} {% endtabs %} -## Callbacks +## Filtering Callbacks -The SfDataGrid provides the following callbacks to notify the filtering stages: +The SfDataGrid provides callbacks to notify the filtering stages. These callbacks allow you to customize the filtering behavior and access filter condition details. ### OnFilterChanging callback -[onFilterChanging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onFilterChanging.html) callback invokes when the filtering is being applied to the particular column through UI filtering. You can return `false` from this callback to restrict the column from being filtered. +The [onFilterChanging](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onFilterChanging.html) callback is invoked when filtering is being applied to a particular column through UI filtering. Return `false` from this callback to prevent filtering on that column. {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + @override Widget build(BuildContext context) { return SfDataGrid( allowFiltering: true, - source: _employeeDataSource, + source: employeeDataSource, onFilterChanging: (DataGridFilterChangeDetails details) { + // Restrict filtering on the Salary column if (details.column.columnName == 'Salary') { return false; } return true; }, + columnWidthMode: ColumnWidthMode.fill, columns: [ GridColumn( columnName: 'ID', @@ -703,8 +719,8 @@ The SfDataGrid provides the following callbacks to notify the filtering stages: child: Text( 'ID', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Name', @@ -714,8 +730,8 @@ The SfDataGrid provides the following callbacks to notify the filtering stages: child: Text( 'Name', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Designation', @@ -725,8 +741,8 @@ The SfDataGrid provides the following callbacks to notify the filtering stages: child: Text( 'Designation', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Salary', @@ -736,10 +752,10 @@ The SfDataGrid provides the following callbacks to notify the filtering stages: child: Text( 'Salary', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), - ] + ], ); } @@ -748,21 +764,26 @@ The SfDataGrid provides the following callbacks to notify the filtering stages: ### OnFilterChanged callback -The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onFilterChanged.html) callback is invoked after filtering is applied to a particular column through UI filtering. You can use this callback to access filter conditions. +The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onFilterChanged.html) callback is invoked after filtering is applied to a particular column through UI filtering. Use this callback to access filter condition details such as the column name, filter type, and filter value. {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + @override Widget build(BuildContext context) { return SfDataGrid( allowFiltering: true, - source: _employeeDataSource, + source: employeeDataSource, onFilterChanged: (DataGridFilterChangeDetails details) { - print('Column Name: ${details.column.columnName}'); - print('Filter Type: ${details.filterConditions.last.type}'); - print('Filter Value: ${details.filterConditions.last.value}'); + debugPrint('Column Name: ${details.column.columnName}'); + if (details.filterConditions.isNotEmpty) { + debugPrint('Filter Type: ${details.filterConditions.last.type}'); + debugPrint('Filter Value: ${details.filterConditions.last.value}'); + } }, + columnWidthMode: ColumnWidthMode.fill, columns: [ GridColumn( columnName: 'ID', @@ -772,8 +793,8 @@ The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/ child: Text( 'ID', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Name', @@ -783,8 +804,8 @@ The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/ child: Text( 'Name', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Designation', @@ -794,8 +815,8 @@ The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/ child: Text( 'Designation', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), GridColumn( columnName: 'Salary', @@ -805,10 +826,10 @@ The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/ child: Text( 'Salary', overflow: TextOverflow.ellipsis, - ) - ) + ), + ), ), - ] + ], ); } @@ -817,7 +838,10 @@ The [onFilterChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/ ## Customizing the filter popup menu options -The `SfDataGrid` provides support to customize the menu options in the filter popup menu. Please refer to the following topics for more information. +The `SfDataGrid` provides support to customize the behavior and appearance of the filter popup menu. The following subsections demonstrate how to customize various aspects of the filter UI. + +> **NOTE** + Filter UI customization options like `filterMode`, `canShowSortingOptions`, and `canShowClearFilterOption` are available through the [FilterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterPopupMenuOptions-class.html) class in the [GridColumn.filterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/filterPopupMenuOptions.html) property. ### Show checkbox or advanced filtering mode @@ -1155,11 +1179,10 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ### Set a custom filter icon -The `SfDataGrid` allows you to change the filter icon by using the [SfDataGridThemeData.filterIcon](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterIcon.html) property. The DataGrid should be wrapped inside the `SfDataGridTheme.` +The `SfDataGrid` allows you to change the filter icon by using the [SfDataGridThemeData.filterIcon](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterIcon.html) property. The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. -The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. So, import the following file. - -By using the [Builder](https://api.flutter.dev/flutter/widgets/Builder-class.html) widget, change the icon based on each state of the filtering, that is, the filter and filtered states. You must return the icons for two states even if you want to change the icon for a specific state. +> **NOTE** + Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply custom filter icons. Use a [Builder](https://api.flutter.dev/flutter/widgets/Builder-class.html) widget to return different icons based on filter states (filtered or not filtered). {% tabs %} {% highlight Dart %} @@ -1242,7 +1265,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ## Change the position of the filter icon -The position of the filter icon can be changed by using the [GridColumn.filterIconPosition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/filterIconPosition.html) property. +The position of the filter icon can be changed by using the [GridColumn.filterIconPosition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/filterIconPosition.html) property. The icon can be positioned at the start or end of the column header using the [ColumnHeaderIconPosition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnHeaderIconPosition.html) enum. {% tabs %} {% highlight Dart %} @@ -1252,47 +1275,55 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, + body: SfDataGrid( + source: employeeDataSource, allowFiltering: true, gridLinesVisibility: GridLinesVisibility.both, headerGridLinesVisibility: GridLinesVisibility.both, + columnWidthMode: ColumnWidthMode.fill, columns: [ GridColumn( - filterIconPosition: ColumnHeaderIconPosition.start, - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + filterIconPosition: ColumnHeaderIconPosition.start, + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerRight, - child: Text('Salary' - ))), + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerRight, + child: Text('Salary'), + ), + ), ], ), ); @@ -1307,6 +1338,9 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; The text style of the filter popup menu can be customized by using the [SfDataGridThemeData.filterPopupTextStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterPopupTextStyle.html) and [SfDataGridThemeData.filterPopupDisabledTextStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterPopupDisabledTextStyle.html) properties. +> **NOTE** + Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply text style customizations. + {% tabs %} {% highlight Dart %} @@ -1316,57 +1350,67 @@ import 'package:syncfusion_flutter_core/theme.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGridTheme( - data: SfDataGridThemeData( - filterPopupTextStyle:GoogleFonts.sacramento( - textStyle: const TextStyle( - fontSize: 25 - )), - filterPopupDisabledTextStyle: GoogleFonts.abhayaLibre( - textStyle: const TextStyle( - fontSize:25 - )),), - child: SfDataGrid( - source: _employeeDataSource, - allowFiltering: true, - columns: [ - GridColumn( + body: SfDataGridTheme( + data: SfDataGridThemeData( + filterPopupTextStyle: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + filterPopupDisabledTextStyle: const TextStyle( + fontSize: 14, + color: Colors.grey, + ), + ), + child: SfDataGrid( + source: employeeDataSource, + allowFiltering: true, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerRight, - child: Text('Salary' - ))), - ], + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerRight, + child: Text('Salary'), + ), + ), + ], + ), ), - )); + ); } {% endhighlight %} @@ -1520,9 +1564,8 @@ By default, the `FilterBehavior.strongDataType` applies to numeric, String, and The `SfDataGrid` provides complete color customization support for the filter popup menu, allowing you to personalize its appearance and enhance its visual appeal. -You can apply custom colors and personalize the filter popup menu by configuring the properties listed below through the `SfDataGridTheme`. To enable this, ensure that the `SfDataGrid` is wrapped inside an `SfDataGridTheme` widget. - -The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. So, make sure to import the following file. +> **NOTE** + The `SfDataGrid` must be wrapped inside an `SfDataGridTheme` widget for appearance customizations to take effect. The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. | Properties | Description | diff --git a/Flutter/datagrid/footer.md b/Flutter/datagrid/footer.md index 70294bbf5..7ee8b799d 100644 --- a/Flutter/datagrid/footer.md +++ b/Flutter/datagrid/footer.md @@ -9,7 +9,9 @@ documentation: ug # Footer in Flutter DataGrid (SfDataGrid) -Creates an additional row that can be displayed under the last row. Widgets can be displayed in the additional row by setting the [SfDataGrid.footer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footer.html) property. +The footer row is an additional row that displays below the last data row in the grid. Widgets can be displayed in the footer row by setting the [SfDataGrid.footer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footer.html) property. + +> **NOTE:** Before implementing the footer functionality, ensure you have set up the SfDataGrid with a valid [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) and configured the necessary columns. {% tabs %} {% highlight Dart %} @@ -74,7 +76,9 @@ Creates an additional row that can be displayed under the last row. Widgets can ## Change the footer row height -An additional row height can be personalized by using the [SfDataGrid.footerHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerHeight.html) property. The default value of the additional row is 49.0. +The footer row height can be customized by using the [SfDataGrid.footerHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerHeight.html) property. The default height of the footer row is 49.0 logical pixels. + +> **NOTE:** When setting a custom footer height, ensure it is sufficient to display all the content without text overflow or clipping. {% tabs %} {% highlight Dart %} @@ -131,7 +135,9 @@ An additional row height can be personalized by using the [SfDataGrid.footerHeig ## Show the footer row always -By default, the additional row will be displayed below the last row. To show the additional row always on the view bottom, simply set the [SfDataGrid.footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) property to 1. +By default, the footer row is displayed below the last data row. To keep the footer visible at the bottom of the grid while scrolling vertically, set the [SfDataGrid.footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) property to 1. + +> **NOTE:** Setting `footerFrozenRowsCount` to 1 freezes the footer row, ensuring it remains visible when users scroll through the data, similar to freezing header rows. {% tabs %} {% highlight Dart %} @@ -185,3 +191,71 @@ By default, the additional row will be displayed below the last row. To show the {% endtabs %} ![flutter datagrid shows footer always on bottom](images/footer/flutter-datagrid-footer-on-bottom.gif) + +## Updating footer content dynamically + +The footer content can be updated dynamically by rebuilding the widget when the data changes. Use a [StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html) or [ValueListenableBuilder](https://api.flutter.dev/flutter/foundation/ValueListenableBuilder-class.html) to reactively update the footer display based on data changes. + +{% tabs %} +{% highlight Dart %} + + @override + Widget build(BuildContext context) { + return SfDataGrid( + source: _employeeDataSource, + footer: StreamBuilder( + stream: _employeeDataSource.rowCountStream, + builder: (context, snapshot) { + return Container( + color: Colors.grey[400], + child: Padding( + padding: EdgeInsets.all(8.0), + child: Text( + 'Total Employees: ${snapshot.data ?? 0}', + style: TextStyle(fontWeight: FontWeight.bold), + ))); + }), + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('ID'))), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'))), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation'))), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'))), + ]); + } + +{% endhighlight %} +{% endtabs %} + +## API reference + +Refer to the following API documentation for footer-related properties: + +* [SfDataGrid.footer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footer.html) — Sets the widget to display as the footer row. +* [SfDataGrid.footerHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerHeight.html) — Sets the height of the footer row. Default value is 49.0. +* [SfDataGrid.footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) — Sets the number of frozen footer rows. Set to 1 to keep the footer visible during vertical scrolling. +* [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — Base class for providing rows to SfDataGrid. + +## See also + +* [Header in Flutter DataGrid](https://help.syncfusion.com/flutter/datagrid/header) +* [Frozen rows and columns in Flutter DataGrid](https://help.syncfusion.com/flutter/datagrid/frozen-pane) diff --git a/Flutter/datagrid/freeze-panes.md b/Flutter/datagrid/freeze-panes.md index 83c1746ff..7c97b8a38 100644 --- a/Flutter/datagrid/freeze-panes.md +++ b/Flutter/datagrid/freeze-panes.md @@ -11,6 +11,8 @@ documentation: ug The rows and columns can freeze in view like in Excel. They can be frozen by setting the following properties. +N> Before implementing freeze panes, ensure you have added the `syncfusion_flutter_datagrid` package to your project and created a `DataGridSource` for your data. For more details, refer to [DataGrid Getting Started](getting-started.md). + @@ -29,7 +31,7 @@ Set the frozen rows count at the top of the SfDataGrid. footerFrozenRowsCount @@ -45,7 +47,31 @@ Set the frozen columns count on the left side of the SfDataGrid. footerFrozenColumnsCount + + + + + + + + + + + +
Property Name -Set the footer rows count at the bottom of the SfDataGrid. +Set the footer frozen rows count at the bottom of the SfDataGrid.
-Set the footer columns on the right side of the SfDataGrid. +Set the footer frozen columns on the right side of the SfDataGrid. +
+frozenPaneElevation + +Customize the elevation effect applied to frozen panes. Default value is 5.0. Set to 0.0 to remove elevation and display only the frozen pane line. +
+frozenPaneLineColor + +Customize the color of the line displayed at the edge of frozen panes. +
+frozenPaneLineWidth + +Customize the width of the line displayed at the edge of frozen panes.
@@ -54,11 +80,14 @@ Set the footer columns on the right side of the SfDataGrid. The columns can be frozen in view at left and right like Excel by setting the [frozenColumnsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenColumnsCount.html) and [footerFrozenColumnsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenColumnsCount.html) properties. -The following code example shows how to freeze a column at left using `frozenColumnsCount`, +The following code example shows how to freeze a column at left using `frozenColumnsCount`: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -147,11 +176,14 @@ The following code example shows how to freeze a column at left using `frozenCol ![flutter datagrid shows frozen column at left](images/frozen-pane/flutter-datagrid-frozen-column.gif) -The following code example shows how to freeze a column at right using the `footerFrozenColumnsCount.` +The following code example shows how to freeze a column at right using the `footerFrozenColumnsCount`: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -249,11 +281,14 @@ The following code example shows how to freeze a column at right using the `foot The rows can be frozen in view at the top and bottom like in Excel by setting the [frozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenRowsCount.html) and [footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) properties. -The following code example shows how to freeze a row at the top using the `frozenRowsCount`, +The following code example shows how to freeze a row at the top using the `frozenRowsCount`: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -341,11 +376,14 @@ The following code example shows how to freeze a row at the top using the `froze ![flutter datagrid shows frozen row at top](images/frozen-pane/flutter-datagrid-frozen-row.gif) -The following code example shows how to freeze a row at the bottom using the `footerFrozenRowsCount.` +The following code example shows how to freeze a row at the bottom using the `footerFrozenRowsCount`: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -443,19 +481,20 @@ N> Header row is frozen by default and works regardless of the `frozenRowsCount` ## Appearance -The `SfDataGrid` allows customizing the appearance of the freeze pane through the [SfDataGridTheme.SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) property. The DataGrid should be wrapped inside the `SfDataGridTheme.` +The `SfDataGrid` allows customizing the appearance of frozen panes through the [SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) property. The DataGrid should be wrapped inside the [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html) widget. -The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. So, import the following file. +The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. Import the required packages: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:syncfusion_flutter_core/theme.dart'; {% endhighlight %} {% endtabs %} -The frozen line will be shown only the [SfDataGridThemeData.frozenPaneElevation](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneElevation.html) property to 0. The freeze pane line and freeze pane width can be changed by [frozenPaneLineColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineColor.html) and [frozenPaneLineWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineWidth.html). +The frozen pane line will be shown only when the [frozenPaneElevation](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneElevation.html) property is set to 0. The frozen pane line color and width can be customized using the [frozenPaneLineColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineColor.html) and [frozenPaneLineWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineWidth.html) properties. {% tabs %} {% highlight Dart %} @@ -557,9 +596,11 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; {% endhighlight %} {% endtabs %} -![flutter datagrid shows freeze pane customization](images/frozen-pane/flutter-datagrid-frozen-pane-customization.png) +![flutter datagrid shows frozen pane customization](images/frozen-pane/flutter-datagrid-frozen-pane-customization.png) + +### Customize frozen pane elevation -The `SfDataGrid` allows customizing the appearance of the freeze pane elevation by using the `SfDataGridThemeData.frozenPaneElevation`. The default value of frozenPaneElevation is 5.0. +The `SfDataGrid` allows customizing the appearance of the frozen pane elevation by using the [frozenPaneElevation](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneElevation.html) property. The default value is 5.0. {% tabs %} {% highlight Dart %} @@ -653,15 +694,19 @@ The `SfDataGrid` allows customizing the appearance of the freeze pane elevation {% endhighlight %} {% endtabs %} -![flutter datagrid shows customization of freeze pane elevation](images/frozen-pane/flutter-datagrid-customized-frozen-elevation.png) +![flutter datagrid shows customization of frozen pane elevation](images/frozen-pane/flutter-datagrid-customized-frozen-elevation.png) -## Hide freeze pane elevation +### Customize frozen pane line appearance -By default, the elevation effect is applied to frozen panes. If you want to hide the freeze pane elevation and show only the frozen pane line, simply set the `SfDataGridThemeData.frozenPaneElevation` property to 0. Customize the appearance of the frozen line by using the `SfDataGridThemeData.frozenPaneLineColor` and `SfDataGridThemeData.frozenPaneLineWidth` properties. +By default, the elevation effect is applied to frozen panes. To hide the elevation and display only the frozen pane line, set the [frozenPaneElevation](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneElevation.html) property to 0. Customize the line appearance using the [frozenPaneLineColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineColor.html) and [frozenPaneLineWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineWidth.html) properties. {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + @override Widget build(BuildContext context) { return Scaffold( @@ -755,3 +800,9 @@ By default, the elevation effect is applied to frozen panes. If you want to hide {% endtabs %} ![flutter datagrid shows how to hide the frozen pane elevation](images/frozen-pane/flutter-datagrid-hide-frozen-elevation.png) + +N> **Header row behavior** — The header row is frozen by default and remains frozen regardless of the `frozenRowsCount` property. This ensures the column headers remain visible while scrolling through data. + +N> **Interaction with other features** — Frozen panes work seamlessly with other DataGrid features including sorting, filtering, selection, and styling. Frozen rows and columns maintain their visual separation during these operations. + +N> **Sample applications** — Refer to the [DataGrid freeze panes sample](https://github.com/syncfusion/flutter-examples/blob/master/lib/samples/datagrid/datagrid_freezepanes.dart) in the Syncfusion Flutter Examples repository for a complete working implementation. diff --git a/Flutter/datagrid/getting-started.md b/Flutter/datagrid/getting-started.md index c427f1c86..777cd8653 100644 --- a/Flutter/datagrid/getting-started.md +++ b/Flutter/datagrid/getting-started.md @@ -9,15 +9,17 @@ documentation: ug # Getting started with Flutter DataGrid (SfDataGrid) -This section explains the steps required to add the DataGrid widget and its features. This section covers only the basic features needed to get started with the Syncfusion® Flutter DataGrid widget. +This section explains the steps required to add the SfDataGrid widget and its features. This section covers only the basic features needed to get started with the Syncfusion® Flutter DataGrid widget. -To get started quickly with Flutter DataGrid, check out this video: +N> **Prerequisites:** Ensure you have Flutter SDK installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. + +To get started quickly with Flutter SfDataGrid, check out this video: -## Add Flutter DataGrid to an application +## Add Flutter SfDataGrid to an application -Create a simple project using the instruction given in the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. +Create a simple project using the instruction given in the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. **Add dependency** @@ -31,7 +33,7 @@ Add the Syncfusion® Flutter DataGrid dependency to your `pubspec.yaml` file. {% endhighlight %} -N> Here **xx.x.xx** denotes the current version of the [`Syncfusion® Flutter DataGrid`](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) package. +N> Here **xx.x.xx** denotes the current version of the [`Syncfusion® Flutter DataGrid`](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) package. Refer to the [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) page to check the latest available version. **Get packages** @@ -55,9 +57,9 @@ Import the following package in your Dart code. {% endhighlight %} {% endtabs %} -## Initialize DataGrid +## Initialize SfDataGrid -Add the SfDataGrid widget as a child of any widget. The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) requires the [source](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/source.html) and [columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) properties. Find more details on these properties in further topics. +Add the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget as a child of any widget. The `SfDataGrid` widget requires the [source](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/source.html) and [columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) properties. The `source` property is required to provide the data to display, and `columns` is required to define the grid structure. Find more details on these properties in further topics. {% tabs %} {% highlight Dart %} @@ -119,9 +121,11 @@ Add the SfDataGrid widget as a child of any widget. The [SfDataGrid](https://pub {% endhighlight %} {% endtabs %} -## Creating Data for an Application +## Creating data for an application + +The `SfDataGrid` requires data to display. Create a data model class and populate it with sample data as shown in the following code example. -The `SfDataGrid` requires data to display. Create a simple data source for the `SfDataGrid` as shown in the following code example. +**Create the Employee model class:** {% tabs %} {% highlight Dart %} @@ -137,7 +141,9 @@ class Employee { {% endhighlight %} {% endtabs %} -Create the collection of Employee data with the required number of data objects. Here, the `getEmployeeData` method which is used to populate the data objects is initialized in `initState()`. +**Create sample employee collection:** + +Create a collection of `Employee` objects in your StatefulWidget. The following code example shows how to initialize the employee data collection in `initState()` method. You will use this data source in the next step. {% tabs %} {% highlight Dart %} @@ -171,15 +177,15 @@ List getEmployeeData() { {% endhighlight %} {% endtabs %} -## Creating DataSource for DataGrid +## Creating data source for SfDataGrid -[DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) is used to obtain the row data for the `SfDataGrid`. So, create the DataSource from the DataGridSource and override the following APIs in it, +[DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) is used to obtain the row data for the `SfDataGrid`. Create a custom `DataGridSource` by extending `DataGridSource` and override the following required properties: -* **`rows`** - Fetches the rows available for data population. Also, it is used to fetch the corresponding data object to process the selection. This contains the collection of the `DataGridRow` where each row contains the collection of the `DataGridCell`. Each cell should have the cell value in the `value` property. The `value` is used to perform the sorting for columns. +* **`rows`** - Returns a list of [DataGridRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRow-class.html) objects. Each `DataGridRow` contains a collection of [DataGridCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCell-class.html) objects with cell values. The cell `value` property is used for sorting and selection operations. -* **`buildRow`** - Fetches the widget for each cell with `DataGridRowAdapter`. +* **`buildRow`** - Returns a [DataGridRowAdapter](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRowAdapter-class.html) that builds the widget for each cell in the row. -`DataGridSource` objects are expected to be long-lived, not recreated with each build. +N> `DataGridSource` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridSource` once in the `initState()` method and reuse it. {% tabs %} {% highlight Dart %} @@ -224,7 +230,9 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -Create an instance of the `DataGridSource` and set this object to the `source` property of the `SfDataGrid`. +**Use the data source in SfDataGrid:** + +Set the initialized `DataGridSource` to the `source` property of the `SfDataGrid` widget in the `build()` method. {% tabs %} {% highlight Dart %} @@ -234,9 +242,13 @@ late EmployeeDataSource _employeeDataSource; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( + body: SfDataGrid( source: _employeeDataSource, - )); + columns: [ + // Define columns here + ], + ), + ); } {% endhighlight %} @@ -247,7 +259,7 @@ Widget build(BuildContext context) { ## Defining columns -The `SfDataGrid` supports adding any widget in a column using the `GridColumn` property. Add the column collection to the `columns` property. +The `SfDataGrid` supports adding any widget in a column using the [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) widget. Add the column collection to the `columns` property. Each `GridColumn` requires a `columnName` that matches the cell names in your data source and a `label` widget to display the column header. {% tabs %} {% highlight Dart %} @@ -302,144 +314,179 @@ The `SfDataGrid` supports adding any widget in a column using the `GridColumn` p ## Selection -The `SfDataGrid` allows you to select one or more rows. The [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property can be set to specify whether the user can select a single row or multiple rows. +The `SfDataGrid` allows you to select one or more rows. Use the [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property to specify the selection behavior: single row or multiple rows. + +**Enable row selection:** {% tabs %} {% highlight Dart %} - @override - Widget build(BuildContext context) { - return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) +@override +Widget build(BuildContext context) { + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ), ), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ) - ) + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ), ), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ) - ) + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ), ), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ) - ) + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ), ), - ], - selectionMode: SelectionMode.multiple, - ) - ); - } + ), + ], + selectionMode: SelectionMode.multiple, + ), + ); +} {% endhighlight %} {% endtabs %} ![flutter datagrid shows rows with selection](images/getting-started/flutter-datagrid-selection.png) -The information about the rows that are selected can be retrieved using the [selectedIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedIndex.html), [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) and [selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) properties in [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html). You need to initialize the `DataGridController` object to the [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/controller.html) property of `SfDataGrid.` +**Retrieve selection information:** + +You can retrieve information about the selected rows using the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html). Initialize a `DataGridController` and assign it to the [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/controller.html) property of `SfDataGrid` to access selection properties: -`DataGridController` objects are expected to be long-lived, not recreated with each build. +* [selectedIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedIndex.html) - Gets the index of the selected row +* [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) - Gets the currently selected row +* [selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) - Gets all selected rows + +N> `DataGridController` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridController` once in your State class and reuse it. {% tabs %} {% highlight Dart %} - final DataGridController _controller = DataGridController(); +final DataGridController _controller = DataGridController(); - @override - Widget build(BuildContext context) { - return Scaffold( - body: Column(children: [ - TextButton( - child: Text('Get Selection Information'), +@override +Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + TextButton( onPressed: () { int selectedIndex = _controller.selectedIndex; - DataGridRow selectedRow = _controller.selectedRow!; + DataGridRow? selectedRow = _controller.selectedRow; List selectedRows = _controller.selectedRows; - print(selectedIndex); - print(selectedRow); - print(selectedRows); - }), - Expanded( + + if (selectedRow != null) { + debugPrint('Selected Index: $selectedIndex'); + debugPrint('Selected Row: $selectedRow'); + debugPrint('All Selected Rows: $selectedRows'); + } else { + debugPrint('No row selected'); + } + }, + child: const Text('Get Selection Information'), + ), + Expanded( child: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( + child: const Text( 'ID', overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), + ), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( + child: const Text( 'Name', overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), + ), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( + child: const Text( 'Designation', overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), + ), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( + child: const Text( 'Salary', overflow: TextOverflow.ellipsis, - ))), - ], - controller: _controller, - selectionMode: SelectionMode.multiple, - )) - ])); - } + ), + ), + ), + ], + controller: _controller, + selectionMode: SelectionMode.multiple, + ), + ), + ], + ), + ); +} {% endhighlight %} {% endtabs %} ->**NOTE** - `SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`. +N> `SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`. + +## Next steps + +* [Styling](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Customize the appearance of SfDataGrid +* [Sorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Enable sorting on columns +* [Filtering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Filter rows based on conditions +* [Editing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Enable cell editing functionality +* [Export](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Export data to various formats + +For more information, refer to the complete [SfDataGrid documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) and the [GitHub samples repository](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid). diff --git a/Flutter/datagrid/grouping.md b/Flutter/datagrid/grouping.md index 6fc4258ac..49f2c5230 100644 --- a/Flutter/datagrid/grouping.md +++ b/Flutter/datagrid/grouping.md @@ -13,6 +13,8 @@ Grouping in a DataGrid involves organizing and categorizing data based on specif By default, the DataGrid doesn't show the group's caption summary value. To display the caption summary value, you need to override the [DataGridSource.buildGroupCaptionCellWidget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildGroupCaptionCellWidget.html) method. This method receives the caption summary value as a parameter, allowing you to return the necessary widget containing the summary value. +> **Note:** Ensure that you have a populated `DataGridSource` with data rows and columns configured. For custom grouping scenarios, you may need the `collection` package for utility methods like `firstWhereOrNull()`. + ## Programmatic grouping ### Add column group @@ -24,11 +26,14 @@ The `ColumnGroup` object consists of the following properties: * `name`: The column name of the `GridColumn` to be grouped. * `sortGroupRows`: Determines whether to group the column with ascending sorting or not. -The following code demonstrates how to apply grouping to a column +The following code demonstrates how to apply grouping to a column: {% tabs %} {% highlight Dart %} +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + class SfDataGridDemoState extends State { List employees = []; late EmployeeDataSource employeeDataSource; @@ -55,8 +60,7 @@ class SfDataGridDemoState extends State { label: Container( padding: EdgeInsets.all(8), alignment: Alignment.center, - child: Text( - 'ID'))), + child: Text('ID'))), GridColumn( columnName: 'Name', label: Container( @@ -129,11 +133,17 @@ class EmployeeDataSource extends DataGridSource { ### Remove column group -To disable column grouping for a particular column, remove that `ColumnGroup` instance using the `DataGridSource.removeColumnGroup`` method. +To disable column grouping for a particular column, remove that `ColumnGroup` instance using the [DataGridSource.removeColumnGroup](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/removeColumnGroup.html) method. {% tabs %} {% highlight Dart %} +import 'package:collection/collection.dart'; + +class SfDataGridDemoState extends State { + List employees = []; + late EmployeeDataSource employeeDataSource; + @override void initState() { super.initState(); @@ -205,6 +215,21 @@ To clear all the column groups, simply call the [DataGridSource.clearColumnGroup {% tabs %} {% highlight Dart %} +class SfDataGridDemoState extends State { + List employees = []; + late EmployeeDataSource employeeDataSource; + + @override + void initState() { + super.initState(); + employees = getEmployeeData(); + employeeDataSource = EmployeeDataSource(employeeData: employees); + employeeDataSource + .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true)); + employeeDataSource + .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: false)); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -215,7 +240,7 @@ To clear all the column groups, simply call the [DataGridSource.clearColumnGroup setState(() {}); employeeDataSource.clearColumnGroups(); }, - child: Text('Clear all column groups')), + child: const Text('Clear all column groups')), Expanded( child: SfDataGrid( source: employeeDataSource, @@ -226,30 +251,31 @@ To clear all the column groups, simply call the [DataGridSource.clearColumnGroup label: Container( padding: EdgeInsets.all(8), alignment: Alignment.center, - child: Text('ID'))), + child: const Text('ID'))), GridColumn( columnName: 'Name', label: Container( padding: EdgeInsets.all(8), alignment: Alignment.center, - child: Text('Name'))), + child: const Text('Name'))), GridColumn( columnName: 'Designation', label: Container( padding: EdgeInsets.all(8), alignment: Alignment.center, - child: Text('Designation', + child: const Text('Designation', overflow: TextOverflow.ellipsis))), GridColumn( columnName: 'Salary', label: Container( padding: EdgeInsets.all(8), alignment: Alignment.center, - child: Text('Salary'))), + child: const Text('Salary'))), ])), ]), ); } +} {% endhighlight %} {% endtabs %} @@ -538,13 +564,21 @@ The [SfDataGrid.groupCollapsed](https://pub.dev/documentation/syncfusion_flutter ## Custom grouping -The `SfDataGrid` provides support to group a column using custom logic when standard grouping techniques aren't sufficient for specific requirements. This can be accomplished by overriding the [DataGridSource.performGrouping](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/performGrouping.html) method. +Use custom grouping when you need to group data based on derived or transformed values, such as salary ranges, age groups, or custom categories that don't directly correspond to column values. This approach provides more flexibility than standard column-based grouping. -The `DataGridSource.performGrouping` method is invoked when grouping is applied to the `SfDataGrid`. Within this method, you can implement custom logic to return a `String` based on your specific requirements. +Custom grouping is implemented by overriding the [DataGridSource.performGrouping](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/performGrouping.html) method. This method is invoked when grouping is applied to the `SfDataGrid`, allowing you to implement custom logic and return a `String` representing the group key for each row. {% tabs %} {% highlight Dart %} +import 'package:collection/collection.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:flutter/material.dart'; + +class SfDataGridDemoState extends State { + List employees = []; + late EmployeeDataSource employeeDataSource; + @override void initState() { super.initState(); @@ -561,10 +595,6 @@ The `DataGridSource.performGrouping` method is invoked when grouping is applied body: SfDataGrid( source: employeeDataSource, allowExpandCollapseGroup: true, - groupExpanded: (group) { - print('Group expanding: ${group.key}'); - print('Group level: ${group.groupLevel}'); - }, columns: [ GridColumn( columnName: 'ID', @@ -594,7 +624,7 @@ The `DataGridSource.performGrouping` method is invoked when grouping is applied ]), ); } - +} class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { @@ -639,21 +669,25 @@ class EmployeeDataSource extends DataGridSource { @override String performGrouping(String columnName, DataGridRow row) { if (columnName == 'Salary') { - final double total = row + final DataGridCell? salaryCell = row .getCells() + .whereType>() .firstWhereOrNull( - (DataGridCell cell) => cell.columnName == columnName)! - .value; - if (total > 100000 && total <= 200000) { - return '> 100 K & <= 150 K'; - } else if (total > 90000 && total <= 100000) { - return '> 90 K & <= 100 K'; - } else if (total > 50000 && total <= 90000) { - return '> 50 K & <= 90 K'; - } else if (total > 30000 && total <= 50000) { - return '> 30 K & <= 50 K'; - } else { - return '<= 30 K'; + (DataGridCell cell) => cell.columnName == columnName); + + if (salaryCell != null) { + final double total = salaryCell.value; + if (total > 100000 && total <= 200000) { + return '> 100 K & <= 200 K'; + } else if (total > 90000 && total <= 100000) { + return '> 90 K & <= 100 K'; + } else if (total > 50000 && total <= 90000) { + return '> 50 K & <= 90 K'; + } else if (total > 30000 && total <= 50000) { + return '> 30 K & <= 50 K'; + } else { + return '<= 30 K'; + } } } return super.performGrouping(columnName, row); @@ -667,7 +701,9 @@ class EmployeeDataSource extends DataGridSource { ## Enable group expand and collapse -The group expand and collapse functionality can be enabled by setting the [SfDataGrid.allowExpandCollapseGroup](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowExpandCollapseGroup.html) property to `true`. The default value of this property is `false.` +The group expand and collapse functionality can be enabled by setting the [SfDataGrid.allowExpandCollapseGroup](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowExpandCollapseGroup.html) property to `true`. The default value of this property is `false`. + +When `allowExpandCollapseGroup` is set to `false`, groups are displayed but users cannot expand or collapse them; all groups remain in their default state as determined by the `autoExpandGroups` property. {% tabs %} {% highlight Dart %} @@ -771,7 +807,7 @@ By default, the SfDataGrid always expands all the groups. All the groups can be ## Programmatically expand and collapse groups -Expanding and collapsing groups programmatically can be achieved using the following `DataGridController` methods, +Expanding and collapsing groups programmatically can be achieved using the following [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) methods: @@ -779,26 +815,113 @@ Expanding and collapsing groups programmatically can be achieved using the follo - - + + - - + + - - + + - - + +
Description
DataGridController.expandAllGroup Expands all the groups in the SfDataGrid expandAllGroupExpands all the groups in the SfDataGrid
DataGridController.collapseAllGroup. Collapses all the groups in the SfDataGrid collapseAllGroupCollapses all the groups in the SfDataGrid
DataGridController.expandGroupsAtLevel. Expands the group based on the group level expandGroupsAtLevelExpands the groups based on the group level
DataGridController.collapseGroupsAtLevel. Collapses the group based on the group level collapseGroupsAtLevelCollapses the groups based on the group level
+The following code example demonstrates how to use these methods: + +{% tabs %} +{% highlight Dart %} + +final DataGridController _dataGridController = DataGridController(); + +@override +Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: Column(children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + _dataGridController.expandAllGroup(); + }, + child: const Text('Expand All'), + ), + ElevatedButton( + onPressed: () { + _dataGridController.collapseAllGroup(); + }, + child: const Text('Collapse All'), + ), + ElevatedButton( + onPressed: () { + _dataGridController.expandGroupsAtLevel(0); + }, + child: const Text('Expand Level 0'), + ), + ], + ), + Expanded( + child: SfDataGrid( + controller: _dataGridController, + source: employeeDataSource, + allowExpandCollapseGroup: true, + columns: [ + GridColumn( + columnName: 'ID', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ), + ]), + ); +} + +{% endhighlight %} +{% endtabs %} + ## Customize the group caption summary row format -The caption summary value is displayed in a caption summary row by the default format `'{ColumnName} : {Key} - {ItemsCount} Items'.` The `{ColumnName}` defines the name of the grouped column, {Key} defines the identical cell value of the group, and `{ItemsCount}` defines the length of the rows in the group. +The caption summary value is displayed in a caption summary row by the default format `'{ColumnName} : {Key} - {ItemsCount} Items'`. The available placeholders for customizing the format are: + +* `{ColumnName}`: The name of the grouped column +* `{Key}`: The identical cell value of the group +* `{ItemsCount}`: The number of rows in the group The format can be customized by using the [SfDataGrid.groupCaptionTitleFormat](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/groupCaptionTitleFormat.html) property. @@ -960,5 +1083,5 @@ The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [sy ## Limitations -* The grouping will be refreshed when performing CRUD operations on the [DataGridSource.rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) and the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html).` Consequently, this action resets the expand and collapse states of the groups based on the [SfDataGrid.autoExpandGroups](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/autoExpandGroups.html) property. -* To prevent unnecessary grouping refresh, ensure that the `SfDataGrid.columns` property is set as an instance. +* Grouping is refreshed when performing CRUD operations on [DataGridSource.rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) or [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html). This action resets expand and collapse states of groups based on the [SfDataGrid.autoExpandGroups](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/autoExpandGroups.html) property. To work around this, update the `rows` collection in-place rather than reassigning it completely. +* To prevent unnecessary grouping refresh, ensure that the `SfDataGrid.columns` property is assigned once as a single instance rather than being recreated on each build or state change. diff --git a/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md b/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md index b7fa81d3d..502333dd0 100644 --- a/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md +++ b/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md @@ -11,7 +11,9 @@ documentation: ug ## Overview -[FlutterFlow](https://app.flutterflow.io/dashboard) enables you to create native applications using its graphical interface, reducing the need to write extensive amounts of code. Additionally, it offers the capability to include custom widgets that are not included in the default [FlutterFlow](https://app.flutterflow.io/dashboard) widget collection. This article explains how to incorporate our SfDataGrid widget as a custom widget in [FlutterFlow](https://app.flutterflow.io/dashboard). +[FlutterFlow](https://app.flutterflow.io/dashboard) enables you to create native applications using its graphical interface, reducing the need to write extensive amounts of code. Additionally, it offers the capability to include custom widgets that are not included in the default [FlutterFlow](https://app.flutterflow.io/dashboard) widget collection. This article explains how to incorporate the SfDataGrid widget as a custom widget in FlutterFlow. + +>**Note**: You need an active FlutterFlow account and basic knowledge of Flutter development to follow this guide. Refer to the [SDK version compatibility](https://help.syncfusion.com/flutter/system-requirements#sdk-version-compatibility) to ensure your FlutterFlow's Flutter version is compatible with the Syncfusion Flutter DataGrid package. ### Create a new project @@ -22,54 +24,62 @@ Navigate to the [FlutterFlow dashboard](https://app.flutterflow.io/dashboard) an 1. Navigate to the `Custom Code` section in the left side navigation menu. 2. Click on the `+ Add` button to open a dropdown menu, then select `Widget`. 3. Update the widget name as desired. -4. Click the `View Boilerplate Code` button on the right side, represented by this icon `[]`. -5. A popup will appear with startup code; locate the button labeled ` Copy to Editor` and click on it. -6. Save the widget. +4. Click the `View Boilerplate Code` button on the right side, represented by the code icon (``). +5. A popup will appear with startup code. Locate the button labeled ` Copy to Editor` and click on it to load the boilerplate code into the editor. +6. Click `Save` to save the custom widget. ![Custom Widget](how-to-section-images/custom-widget.png) ### Add DataGrid widget as a dependency 1. Click on `+ Add Dependency`, a text editor will appear. -2. Navigate to [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) in [pub.dev](https://pub.dev/) and copy the dependency name and version using the `Copy to Clipboard` option. +2. Navigate to the [Syncfusion Flutter DataGrid package](https://pub.dev/packages/syncfusion_flutter_DataGrid) on pub.dev and copy the dependency name and version using the `Copy to Clipboard` option. ![Version](how-to-section-images/copy-version.png) 3. Paste the copied dependency into the text editor, then click `Refresh` and `Save` it. ->**Note**: The live version of [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) has been migrated to the latest version of Flutter SDK. To ensure compatibility, check [FlutterFlow](https://app.flutterflow.io/dashboard)'s current Flutter version and obtain the corresponding version of [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) by referring to the [SDK compatibility](https://help.syncfusion.com/flutter/system-requirements#sdk-version-compatibility). - -![Dependency](how-to-section-images/dependency.png) +>**Note**: If you need a specific version instead of the latest, remove the caret (^) prefix in the version number. For example, change `^21.3.0` to `21.3.0` to lock to that exact version. ->**Note**: If you are using an older version of a dependency instead of the latest one, remove the caret symbol (^) prefix in the version number after pasting the dependency. For example, change `^21.3.0` to `21.3.0`. +>**Note**: The SfDataGrid package depends on the [Syncfusion Flutter Core](https://pub.dev/packages/syncfusion_flutter_core) package. Make sure to add it as a dependency using the same steps above. ->**Note**: Since [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) depends on the [Syncfusion Flutter Core](https://pub.dev/packages/syncfusion_flutter_core) package, make sure to add it as a dependency following the same steps mentioned above. +![Dependency](how-to-section-images/dependency.png) ### Import the package -1. Navigate to the `Installing` tab on the [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) page. Under the `Import it` section, copy the package import statement. +1. Navigate to the **Installing** tab on the [Syncfusion Flutter DataGrid package](https://pub.dev/packages/syncfusion_flutter_DataGrid) page. Under the **Import it** section, copy the package import statement. ![Package](how-to-section-images/copy-package.png) -2. Paste the copied import statement into the code editor and then `Save` it. +2. Paste the copied import statement into the code editor and click `Save`. ![Import](how-to-section-images/import-package-flutterflow.png) ### Add widget code snippet in code editor -1. Navigate to the [Example](https://pub.dev/packages/syncfusion_flutter_DataGrid/example) tab in [Syncfusion Flutter DataGrid](https://pub.dev/packages/syncfusion_flutter_DataGrid) and copy the widget specific codes. +1. Navigate to the **Example** tab in the [Syncfusion Flutter DataGrid package](https://pub.dev/packages/syncfusion_flutter_DataGrid/example) page and copy the widget code example. ![Code](how-to-section-images/code-snippet.png) -2. Paste the copied code sample into the code editor, click `Format Code`, and `Save` it. +2. Paste the copied code into the editor, click `Format Code` to format it to standard style, and then click `Save`. ![Code snippet](how-to-section-images/Adding-code-snippent.png) -### Compiling the codes +### Compiling the code -1. Click the 'Compile Code' button located in the top right corner. -2. If there are no errors, save the process. If errors are present, fix them and compile the code again. Once the code has been successfully compiled, save the process. +1. Click the **Compile Code** button located in the top right corner. +2. Wait for the compilation to complete (typically 2-3 minutes). The status will display at the top of the editor. +3. Once compilation succeeds, a confirmation message will appear. If errors occur, review the error messages, fix the code, and compile again. +4. Click `Save` after successful compilation. ![Compile code](how-to-section-images/compile-code.png) ->**Note**: The compilation progress takes 2 to 3 minutes to complete. +>**Note**: Compilation typically takes 2 to 3 minutes. The editor will display compilation status and any errors encountered during the build process. -### Utilizing the custom widget +### Using the custom widget in your app -1. Navigate to `Widget Palette` located in the left side navigation menu. -2. Click on the `Components` tab. -3. Your custom widget will be under `Custom Code Widgets`. Drag and drop the custom widget to your page. +1. Navigate to **Widget Palette** in the left side navigation menu. +2. Click on the **Components** tab. +3. Locate your custom widget under **Custom Code Widgets**. Drag and drop it onto your page. +4. Configure the SfDataGrid properties and data source as needed. Refer to the [SfDataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/) for detailed configuration options. +5. Run your FlutterFlow app to verify the SfDataGrid widget displays correctly. ![Page](how-to-section-images/page.png) + +## See also + +- [Syncfusion Flutter DataGrid documentation](https://help.syncfusion.com/flutter/datagrid/overview) +- [SfDataGrid GitHub examples](https://github.com/syncfusion/flutter-examples/tree/master/lib/samples/datagrid) +- [Syncfusion Flutter DataGrid API reference](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/) diff --git a/Flutter/datagrid/load-more.md b/Flutter/datagrid/load-more.md index 88a02a389..965809332 100644 --- a/Flutter/datagrid/load-more.md +++ b/Flutter/datagrid/load-more.md @@ -7,26 +7,68 @@ control: SfDataGrid documentation: ug --- -# Load more in Flutter Datagrid (SfDataGrid) +# Load more in Flutter DataGrid (SfDataGrid) -The datagrid provides support to display an interactive view when the grid reaches its maximum offset while scrolling down. You can use [loadMoreViewBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/loadMoreViewBuilder.html) builder to display the view at bottom of datagrid. +The SfDataGrid widget provides support to display an interactive view when the grid reaches its maximum offset while scrolling down. You can use the [loadMoreViewBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/loadMoreViewBuilder.html) property to display a custom view at the bottom of the grid. -You should override the [DataGridSource.handleLoadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleLoadMoreRows.html) method to load more rows and then notify the datagrid about the changes. The `DataGridSource.handleLoadMoreRows` can be called to load more rows from this builder by using the [loadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/LoadMoreRows.html) function which is passed as a parameter to `loadMoreViewBuilder`. +To implement load more functionality, override the [DataGridSource.handleLoadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleLoadMoreRows.html) method to load additional rows and notify the grid about the changes. The `handleLoadMoreRows` method is automatically called when the user scrolls to the bottom of the grid. Use the [LoadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/LoadMoreRows.html) function, passed as a parameter to `loadMoreViewBuilder`, to trigger row loading. + +**NOTE** +Requires `syncfusion_flutter_datagrid` package. Refer to the [getting started](https://help.syncfusion.com/flutter/datagrid/getting-started) guide for setup instructions. ## Infinite scrolling -Infinite Scrolling is an approach that can be used to load more rows to the datagrid whenever the datagrid reaches the bottom. +Infinite scrolling automatically loads more rows as the user scrolls to the bottom of the grid, creating a seamless continuous data experience. This approach is ideal when you have a large dataset and want to load data progressively without user interaction. -The following example demonstrates infinite scrolling by showing the circular progress indicator until the rows are loaded when the datagrid reaches the bottom, +The following example demonstrates infinite scrolling by displaying a circular progress indicator while rows are being loaded: {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'dart:math'; + +class Employee { + Employee(this.id, this.name, this.designation, this.salary); + final int id; + final String name; + final String designation; + final int salary; +} +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return SfDataGrid( + return const MaterialApp(home: Home()); + } +} + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Load More - Infinite Scrolling')), + body: SfDataGrid( source: _employeeDataSource, loadMoreViewBuilder: (BuildContext context, LoadMoreRows loadMoreRows) { Future loadRows() async { @@ -96,10 +138,27 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; 'Salary', overflow: TextOverflow.ellipsis, ))) - ]); + ]), + ); } +} class EmployeeDataSource extends DataGridSource { + static final List _employees = [ + Employee(1001, 'James', 'Project Lead', 20000), + Employee(1002, 'Kathryn', 'Manager', 30000), + Employee(1003, 'Lara', 'Developer', 15000), + Employee(1004, 'Michael', 'Designer', 15000), + Employee(1005, 'Andrew', 'Developer', 15000), + Employee(1006, 'Gail', 'Manager', 25000), + Employee(1007, 'Nancy', 'CEO', 50000), + Employee(1008, 'Margaret', 'Developer', 15000), + Employee(1009, 'Steven', 'Developer', 15000), + Employee(1010, 'Michael', 'System Analyst', 20000), + Employee(1011, 'Robert', 'Developer', 15000), + Employee(1012, 'Laura', 'Developer', 15000), + ]; + EmployeeDataSource() { buildDataGridRows(); } @@ -118,7 +177,7 @@ class EmployeeDataSource extends DataGridSource { dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, - padding: EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, @@ -128,7 +187,8 @@ class EmployeeDataSource extends DataGridSource { @override Future handleLoadMoreRows() async { - await Future.delayed(Duration(seconds: 5)); + // Simulate network delay for loading data + await Future.delayed(const Duration(seconds: 2)); _addMoreRows(_employees, 15); buildDataGridRows(); notifyListeners(); @@ -148,15 +208,15 @@ class EmployeeDataSource extends DataGridSource { } void _addMoreRows(List employees, int count) { - final Random _random = Random(); + final Random random = Random(); final startIndex = employees.isNotEmpty ? employees.length : 0, endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { employees.add(Employee( 1000 + i, - _names[_random.nextInt(_names.length - 1)], - _designation[_random.nextInt(_designation.length - 1)], - 10000 + _random.nextInt(10000), + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), )); } } @@ -193,24 +253,63 @@ class EmployeeDataSource extends DataGridSource { {% endtabs %} **NOTE** - Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-do-the-infinite-scrolling-in-syncfusion-flutter-datatable). + Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-do-the-infinite-scrolling-in-syncfusion-flutter-datatable). ![flutter datagrid shows load more with infinite scrolling behavior](images/load-more/flutter-datagrid-load-more-infinite-scrolling.gif) ## Load more button -Showing load more button is an approach that can be used to load more rows to the datagrid by tapping a button that you load from the `SfDataGrid.loadMoreViewBuilder` builder. The button will be loaded when vertical scrolling is reached at the end of the datagrid. +You can display a load more button that the user can tap to load additional rows on demand. This approach gives users explicit control over data loading rather than automatic loading as with infinite scrolling. -The following example demonstrates how to show the button when vertical scrolling is reached at the end of the datagrid and display the circular indicator until the rows are loaded when you tap that button. In the onPressed flat button callback, you can call the `loadMoreRows` function to add more rows, +The following example demonstrates how to display a button when vertical scrolling reaches the end of the grid, show a loading indicator while rows are being fetched, and load more rows when the button is tapped by calling the `loadMoreRows` function: {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'dart:math'; + +class Employee { + Employee(this.id, this.name, this.designation, this.salary); + final int id; + final String name; + final String designation; + final int salary; +} + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override + Widget build(BuildContext context) { + return const MaterialApp(home: Home()); + } +} + +class Home extends StatefulWidget { + const Home({Key? key}) : super(key: key); + @override + State createState() => _HomeState(); +} + +class _HomeState extends State { + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(); + } @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + appBar: AppBar(title: const Text('Load More - Button')), + body: SfDataGrid( source: _employeeDataSource, loadMoreViewBuilder: (BuildContext context, LoadMoreRows loadMoreRows) { bool showIndicator = false; @@ -223,10 +322,10 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, - border: BorderDirectional( + border: const BorderDirectional( top: BorderSide( width: 1.0, color: Color.fromRGBO(0, 0, 0, 0.26)))), - child: CircularProgressIndicator( + child: const CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(Colors.deepPurple))); } else { return Container( @@ -235,37 +334,31 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; alignment: Alignment.center, decoration: BoxDecoration( color: Colors.white, - border: BorderDirectional( + border: const BorderDirectional( top: BorderSide( width: 1.0, color: Color.fromRGBO(0, 0, 0, 0.26)))), - child: Container( + child: SizedBox( height: 36.0, width: 142.0, child: TextButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.all(Colors.purple)), - child: Text('LOAD MORE', + child: const Text('LOAD MORE', style: TextStyle(color: Colors.white)), onPressed: () async { - // To avoid the "Error: setState() called after dispose():" - // while scrolling the datagrid vertically and displaying the - // load more view, current load more view is checked whether - // loaded widget is mounted or not. + // Check if the widget is still mounted to avoid + // "setState() called after dispose()" errors if (context is StatefulElement && context.state.mounted) { setState(() { showIndicator = true; }); } - // Call the loadMoreRows function to call the - // DataGridSource.handleLoadMoreRows method. So, additional - // rows can be added from handleLoadMoreRows method. + // Call the loadMoreRows function to trigger + // DataGridSource.handleLoadMoreRows method await loadMoreRows(); - // To avoid the "Error: setState() called after dispose():" - // while scrolling the datagrid vertically and displaying the - // load more view, current load more view is checked whether - // loaded widget is mounted or not. + // Reset the indicator state when loading completes if (context is StatefulElement && context.state.mounted) { setState(() { @@ -313,10 +406,27 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; 'Salary', overflow: TextOverflow.ellipsis, ))) - ]); + ]), + ); } +} class EmployeeDataSource extends DataGridSource { + static final List _employees = [ + Employee(1001, 'James', 'Project Lead', 20000), + Employee(1002, 'Kathryn', 'Manager', 30000), + Employee(1003, 'Lara', 'Developer', 15000), + Employee(1004, 'Michael', 'Designer', 15000), + Employee(1005, 'Andrew', 'Developer', 15000), + Employee(1006, 'Gail', 'Manager', 25000), + Employee(1007, 'Nancy', 'CEO', 50000), + Employee(1008, 'Margaret', 'Developer', 15000), + Employee(1009, 'Steven', 'Developer', 15000), + Employee(1010, 'Michael', 'System Analyst', 20000), + Employee(1011, 'Robert', 'Developer', 15000), + Employee(1012, 'Laura', 'Developer', 15000), + ]; + EmployeeDataSource() { buildDataGridRows(); } @@ -335,7 +445,7 @@ class EmployeeDataSource extends DataGridSource { dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, - padding: EdgeInsets.symmetric(horizontal: 16.0), + padding: const EdgeInsets.symmetric(horizontal: 16.0), child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, @@ -345,7 +455,8 @@ class EmployeeDataSource extends DataGridSource { @override Future handleLoadMoreRows() async { - await Future.delayed(Duration(seconds: 5)); + // Simulate network delay for loading data + await Future.delayed(const Duration(seconds: 2)); _addMoreRows(_employees, 15); buildDataGridRows(); notifyListeners(); @@ -365,15 +476,15 @@ class EmployeeDataSource extends DataGridSource { } void _addMoreRows(List employees, int count) { - final Random _random = Random(); + final Random random = Random(); final startIndex = employees.isNotEmpty ? employees.length : 0, endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { employees.add(Employee( 1000 + i, - _names[_random.nextInt(_names.length - 1)], - _designation[_random.nextInt(_designation.length - 1)], - 10000 + _random.nextInt(10000), + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), )); } } @@ -410,6 +521,32 @@ class EmployeeDataSource extends DataGridSource { {% endtabs %} **NOTE** - Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-rows-on-demand-in-Syncfusion-Flutter-datatable). + Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-rows-on-demand-in-Syncfusion-Flutter-datatable). ![flutter datagrid shows load more button behavior](images/load-more/flutter-datagrid-load-more-button.gif) + +## Choosing between infinite scrolling and button approach + +- **Infinite scrolling**: Best for continuous data browsing experiences where users don't need explicit control. Data loads automatically when they reach the bottom, creating a seamless experience. +- **Load more button**: Best when you want to give users explicit control over when data loads, or when automatic loading might consume excessive network bandwidth. + +## Best practices + +- **Batch size**: Load rows in reasonable batches (e.g., 10-20 rows) to balance performance and user experience. +- **Loading state**: Always provide visual feedback while loading to indicate that data is being fetched. +- **Handling completion**: When all data is loaded, modify your data source to stop triggering load operations. You can implement a flag to track this: + + ```dart + @override + Future handleLoadMoreRows() async { + if (_hasMoreData) { + // Load rows + _hasMoreData = _employees.length < _totalRecords; + } + } + ``` + +- **Error handling**: Implement proper error handling in your load more logic to gracefully handle network failures and retry options. + +**NOTE** +Refer to the [DataGridSource API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) for more information about load more row handling. diff --git a/Flutter/datagrid/localization.md b/Flutter/datagrid/localization.md index ed0ec0a38..476757542 100644 --- a/Flutter/datagrid/localization.md +++ b/Flutter/datagrid/localization.md @@ -13,6 +13,8 @@ documentation: ug ### Localization in filter pop-up menu By default, the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) filter popup menu supports US English localizations. You can change the other languages by specifying the `MaterialApp` properties and adding the `flutter_localizations` and [syncfusion_localizations](https://pub.dev/packages/syncfusion_localizations) package to your application. +The following locales are supported: Chinese (zh), Arabic (ar), Japanese (ja), Hindi (hi), French (fr), German (de), Spanish (es), Portuguese (pt), Russian (ru), and more. If a locale is not specified in `supportedLocales`, the app defaults to the first supported locale. + To use `flutter_localizations` and `syncfusion_localizations`, add the package as a dependency to the `pubspec.yaml` file. {% highlight dart %} @@ -24,6 +26,8 @@ syncfusion_localizations: ^24.2.7 {% endhighlight %} +> **Note:** Run `flutter pub get` to fetch the newly added dependencies. + Next, import the `flutter_localizations` and `syncfusion_localizations` library. {% highlight dart %} @@ -33,7 +37,7 @@ import 'package:syncfusion_localizations/syncfusion_localizations.dart'; {% endhighlight %} -Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations/delegate-constant.html) in the `localizationsDelegates,` which is used to localize the static string available in the data pager and specify the `supportedLocales` as well. +Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations/delegate-constant.html) in the `localizationsDelegates,` which is used to localize the static strings available in the filter popup and specify the `supportedLocales` as well. {% tabs %} {% highlight Dart %} @@ -58,7 +62,7 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation title: const Text('Syncfusion Flutter DataGrid'), ), body: SfDataGrid( - source: employeeDataSource, + source: _employeeDataSource, columnWidthMode: ColumnWidthMode.fill, gridLinesVisibility: GridLinesVisibility.both, headerGridLinesVisibility: GridLinesVisibility.both, @@ -102,13 +106,22 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation {% endhighlight %} {% endtabs %} +> **Note:** After adding the packages, hot reload or restart your app to apply the localization changes. + flutter datagrid localization ## Localization in Flutter DataPager (SfDataPager) -By default, the [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) widget supports US English localizations. You can change the other languages by specifying the `MaterialApp` properties and adding the `flutter_localizations` package to your application. +By default, the [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) widget supports US English localizations. You can change the language by specifying the `MaterialApp` properties and adding the necessary localization packages to your application. + +The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) supports two localization scenarios: + +1. **Basic localization (UI labels)** - Using `flutter_localizations` +2. **Complete localization (static strings)** - Using both `flutter_localizations` and `syncfusion_localizations` -To use `flutter_localizations`, add the package as a dependency to the `pubspec.yaml` file. +### Basic DataPager Localization + +To localize the basic UI elements, add `flutter_localizations` to your `pubspec.yaml` file: {% highlight dart %} @@ -118,198 +131,296 @@ flutter_localizations: {% endhighlight %} -Next, import the `flutter_localizations` library and specify [localizationsDelegates](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) and `supportedLocales` for `MaterialApp`. +> **Note:** Run `flutter pub get` to fetch the newly added dependency. + +Next, import the `flutter_localizations` library and specify [localizationsDelegates](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) and `supportedLocales` for `MaterialApp`: {% tabs %} {% highlight Dart %} import 'package:flutter_localizations/flutter_localizations.dart'; - final int rowsPerPage = 15; +final int rowsPerPage = 15; + +class Employee { + Employee({ + required this.id, + required this.name, + required this.designation, + required this.salary, + }); + final int id; + final String name; + final String designation; + final double salary; +} + +class EmployeeDataSource extends DataGridSource { + EmployeeDataSource({required List employeeData}) { + _employeeData = employeeData; + } + + late List _employeeData; @override - Widget build(BuildContext context) { - return MaterialApp( - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: [ - const Locale('zh'), - const Locale('ar'), - const Locale('ja'), - ], - locale: const Locale('zh'), - home: Scaffold( - appBar: AppBar( - title: Text('DataPager'), - ), - body: LayoutBuilder(builder: (context, constraints) { - return Column(children: [ - SizedBox( - height: constraints.maxHeight - 60, - width: constraints.maxWidth, - child: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ])), - Container( - height: 60, - width: constraints.maxWidth, - child: SfDataPager( - delegate: _employeeDataSource, - pageCount: _employees.length / rowsPerPage, - visibleItemsCount: 5, - direction: Axis.horizontal, - )) - ]); - }))); + List get rows => _employeeData + .map((dataRow) => DataGridRow(cells: [ + DataGridCell(columnName: 'id', value: dataRow.id), + DataGridCell(columnName: 'name', value: dataRow.name), + DataGridCell(columnName: 'designation', value: dataRow.designation), + DataGridCell(columnName: 'salary', value: dataRow.salary), + ])) + .toList(); + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: row.getCells().map((dataCell) { + return Container( + alignment: Alignment.center, + padding: const EdgeInsets.all(8.0), + child: Text(dataCell.value.toString()), + ); + }).toList(), + ); } +} + +@override +Widget build(BuildContext context) { + final EmployeeDataSource _employeeDataSource = EmployeeDataSource( + employeeData: [ + Employee(id: 10001, name: 'James', designation: 'Project Lead', salary: 20000), + Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), + Employee(id: 10005, name: 'Martin', designation: 'Developer', salary: 15000), + ], + ); + + return MaterialApp( + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: const [ + Locale('zh'), + Locale('ar'), + Locale('ja'), + ], + locale: const Locale('zh'), + home: Scaffold( + appBar: AppBar( + title: const Text('DataPager'), + ), + body: LayoutBuilder(builder: (context, constraints) { + return Column(children: [ + SizedBox( + height: constraints.maxHeight - 60, + width: constraints.maxWidth, + child: SfDataGrid( + source: _employeeDataSource, + columns: const [ + GridColumn( + columnName: 'id', + label: Center(child: Text('ID')), + ), + GridColumn( + columnName: 'name', + label: Center(child: Text('Name')), + ), + GridColumn( + columnName: 'designation', + label: Center(child: Text('Designation')), + ), + GridColumn( + columnName: 'salary', + label: Center(child: Text('Salary')), + ), + ], + ), + ), + Container( + height: 60, + width: constraints.maxWidth, + child: SfDataPager( + delegate: _employeeDataSource, + pageCount: _employeeDataSource.rows.length / rowsPerPage, + visibleItemsCount: 5, + direction: Axis.horizontal, + ), + ) + ]); + }), + ), + ); +} {% endhighlight %} {% endtabs %} -## Localize the static string in DataPager +> **Note:** After adding the packages, hot reload or restart your app to apply the localization changes. + +flutter datagrid localization + +### Localize Static Strings in DataPager -Static strings in the data pager can be localized using the [syncfusion_localizations](https://pub.dev/packages/syncfusion_localizations) package and specifying `localizationsDelegates` in `MaterialApp`. +Static strings in the [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) (such as pagination labels and navigation text) can be localized using the [syncfusion_localizations](https://pub.dev/packages/syncfusion_localizations) package. -To use `syncfusion_localizations`, add the package as a dependency to the `pubspec.yaml` file. +To use `syncfusion_localizations`, add it as a dependency to the `pubspec.yaml` file: {% highlight dart %} dependencies: -syncfusion_localizations: ^18.3.35 +flutter_localizations: + sdk: flutter +syncfusion_localizations: ^24.2.7 {% endhighlight %} -Next, import the `syncfusion_localizations` library. +> **Note:** Run `flutter pub get` to fetch the newly added dependencies. + +Next, import both `flutter_localizations` and `syncfusion_localizations` libraries: {% highlight dart %} +import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:syncfusion_localizations/syncfusion_localizations.dart'; {% endhighlight %} -Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations/delegate-constant.html) in the `localizationsDelegates,` which is used to localize the static string available in the data pager and specify the `supportedLocales` as well. +Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations/delegate-constant.html) in the `localizationsDelegates,` which is used to localize the static strings available in the DataPager and specify the `supportedLocales` as well: {% tabs %} {% highlight Dart %} - final int rowsPerPage = 15; +final int rowsPerPage = 15; + +class Employee { + Employee({ + required this.id, + required this.name, + required this.designation, + required this.salary, + }); + final int id; + final String name; + final String designation; + final double salary; +} + +class EmployeeDataSource extends DataGridSource { + EmployeeDataSource({required List employeeData}) { + _employeeData = employeeData; + } + + late List _employeeData; @override - Widget build(BuildContext context) { - return MaterialApp( - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - SfGlobalLocalizations.delegate - ], - supportedLocales: [ - const Locale('zh'), - const Locale('ar'), - const Locale('ja'), - ], - locale: const Locale('zh'), - home: Scaffold( - appBar: AppBar( - title: Text('DataPager'), - ), - body: LayoutBuilder(builder: (context, constraints) { - return Column(children: [ - SizedBox( - height: constraints.maxHeight - 60, - width: constraints.maxWidth, - child: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ])), - Container( - height: 60, - width: constraints.maxWidth, - child: SfDataPager( - delegate: _employeeDataSource, - pageCount: _employees.length / rowsPerPage, - visibleItemsCount: 5, - direction: Axis.horizontal, - )) - ]); - }))); + List get rows => _employeeData + .map((dataRow) => DataGridRow(cells: [ + DataGridCell(columnName: 'id', value: dataRow.id), + DataGridCell(columnName: 'name', value: dataRow.name), + DataGridCell(columnName: 'designation', value: dataRow.designation), + DataGridCell(columnName: 'salary', value: dataRow.salary), + ])) + .toList(); + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: row.getCells().map((dataCell) { + return Container( + alignment: Alignment.center, + padding: const EdgeInsets.all(8.0), + child: Text(dataCell.value.toString()), + ); + }).toList(), + ); } +} + +@override +Widget build(BuildContext context) { + final EmployeeDataSource _employeeDataSource = EmployeeDataSource( + employeeData: [ + Employee(id: 10001, name: 'James', designation: 'Project Lead', salary: 20000), + Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), + Employee(id: 10005, name: 'Martin', designation: 'Developer', salary: 15000), + ], + ); + + return MaterialApp( + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + SfGlobalLocalizations.delegate, + ], + supportedLocales: const [ + Locale('zh'), + Locale('ar'), + Locale('ja'), + ], + locale: const Locale('zh'), + home: Scaffold( + appBar: AppBar( + title: const Text('DataPager'), + ), + body: LayoutBuilder(builder: (context, constraints) { + return Column(children: [ + SizedBox( + height: constraints.maxHeight - 60, + width: constraints.maxWidth, + child: SfDataGrid( + source: _employeeDataSource, + columns: const [ + GridColumn( + columnName: 'id', + label: Center(child: Text('ID')), + ), + GridColumn( + columnName: 'name', + label: Center(child: Text('Name')), + ), + GridColumn( + columnName: 'designation', + label: Center(child: Text('Designation')), + ), + GridColumn( + columnName: 'salary', + label: Center(child: Text('Salary')), + ), + ], + ), + ), + Container( + height: 60, + width: constraints.maxWidth, + child: SfDataPager( + delegate: _employeeDataSource, + pageCount: _employeeDataSource.rows.length / rowsPerPage, + visibleItemsCount: 5, + direction: Axis.horizontal, + ), + ) + ]); + }), + ), + ); +} {% endhighlight %} {% endtabs %} +> **Note:** After adding the packages, hot reload or restart your app to apply the localization changes. Supported locales include Chinese (zh), Arabic (ar), Japanese (ja), Hindi (hi), French (fr), German (de), Spanish (es), Portuguese (pt), Russian (ru), and more. See [SfGlobalLocalizations](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations-class.html) for the complete list. + flutter datagrid localization + +## See also + +* [SfDataGrid API Documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) +* [SfDataPager API Documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) +* [Syncfusion Localizations Package](https://pub.dev/packages/syncfusion_localizations) +* [Flutter Localizations Documentation](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) diff --git a/Flutter/datagrid/overview.md b/Flutter/datagrid/overview.md index e96dbc37f..aa9e7adfe 100644 --- a/Flutter/datagrid/overview.md +++ b/Flutter/datagrid/overview.md @@ -11,29 +11,58 @@ documentation: ug The Syncfusion® Flutter DataGrid is used to display and manipulate data in a tabular view. It is built from the ground up to achieve the best possible performance, even when loading large amounts of data. +N> **Note:** The SfDataGrid widget is compatible with iOS, Android, Web, macOS, and Windows platforms. Ensure you have Flutter SDK 3.0 or later installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. + ![Overview Flutter Datagrid](images/overview/flutter-datagrid-overview.png) ## Key Features -* **Column types** - Display any widget in each column, allowing for flexible content presentation. -* **Column sizing** - Configure column widths with various sizing options. Automatically adjust columns based on cell content to enhance readability. -* **Row height** - Customize heights for header and data rows. Automatically adjust row heights based on cell content. Set different heights for specific rows as needed. -* **Editing** - Enable users to modify cell values with support for custom editor widgets based on column types. -* **Sorting** - Sort data in ascending or descending order across single or multiple columns. -* **Selection** - Select one or more rows with keyboard navigation support for web platforms. -* **Filtering** - Filter data interactively similar to Excel with support for text, numeric, and date-time filtering. Programmatic filtering is also available. -* **Column Drag and Drop** - Reorder columns by dragging and dropping them to desired positions. -* **Column resizing** - Adjust column widths by dragging the right edge of column headers. -* **Exporting** - Export data to Excel and PDF formats. -* **Styling** - Customize the appearance of cells and headers with support for conditional styling. -* **Stacked headers** - Create unbound header rows that span across multiple rows and columns. -* **Load more** - Display an interactive view when scrolling reaches the bottom of the grid, enabling on-demand data loading. -* **Paging** - Load data in segments. It is useful when loading huge amounts of data. -* **Freeze Panes** - Freeze the rows and columns when scrolling the grid. -* **Swiping** - Implement swipe actions (left-to-right or right-to-left) for operations like deleting or editing rows. -* **Footer** - Show an additional row that can be displayed under the last row. Widgets can also be displayed in the footer row. -* **Pull to refresh** - Allows users to refresh data when the DataGrid is pulled down. -* **Theme** - Use a dark or light theme. -* **Accessibility** - Ensure screen readers can properly access and navigate the DataGrid. -* **Right to Left (RTL)** - Support right-to-left layouts for languages like Hebrew and Arabic. +### Data Presentation +* [**Column types**](column-types.md) - Display any widget in each column, allowing for flexible content presentation. +* [**Column sizing**](columns-sizing.md) - Configure column widths with various sizing options. Automatically adjust columns based on cell content to enhance readability. +* [**Row height**](row-height-customization.md) - Customize heights for header and data rows. Automatically adjust row heights based on cell content. Set different heights for specific rows as needed. +* [**Styling**](styles.md) - Customize the appearance of cells and headers with support for conditional styling. +* [**Stacked headers**](stacked-headers.md) - Create unbound header rows that span across multiple rows and columns. +* [**Footer**](footer.md) - Show an additional row that can be displayed under the last row. Widgets can also be displayed in the footer row. + +### Data Manipulation +* [**Editing**](editing.md) - Enable users to modify cell values with support for custom editor widgets based on column types. +* [**Sorting**](sorting.md) - Sort data in ascending or descending order across single or multiple columns. +* [**Filtering**](filtering.md) - Filter data interactively similar to Excel with support for text, numeric, and date-time filtering. Programmatic filtering is also available. +* [**Selection**](selection.md) - Select one or more rows with keyboard navigation support for web platforms. +* [**Swiping**](swiping.md) - Implement swipe actions (left-to-right or right-to-left) for operations like deleting or editing rows. + +### Layout and Navigation +* [**Column Drag and Drop**](column-drag-and-drop.md) - Reorder columns by dragging and dropping them to desired positions. +* [**Column resizing**](columns-resizing.md) - Adjust column widths by dragging the right edge of column headers. +* [**Freeze Panes**](freeze-panes.md) - Freeze the rows and columns when scrolling the grid. +* [**Scrolling**](scrolling.md) - Scroll through large datasets efficiently with optimized rendering. + +### Data Loading and Performance +* [**Load more**](load-more.md) - Display an interactive view when scrolling reaches the bottom of the grid, enabling on-demand data loading. +* [**Paging**](paging.md) - Load data in segments. It is useful when loading huge amounts of data. +* [**Pull to refresh**](pull-to-refresh.md) - Allows users to refresh data when the DataGrid is pulled down. + +### Export and Integration +* [**Exporting**](export-to-excel.md) - Export data to [Excel](export-to-excel.md) and [PDF](export-to-pdf.md) formats. +* [**Grouping**](grouping.md) - Group rows by one or more columns for better data organization. +* [**Summaries**](summaries.md) - Display aggregate values for grouped or all data. + +### Customization and Accessibility +* [**Theme**](themes.md) - Use a dark or light theme. +* [**Accessibility**](accessibility.md) - Ensure screen readers can properly access and navigate the DataGrid. +* [**Right to Left (RTL)**](right-to-left.md) - Support right-to-left layouts for languages like Hebrew and Arabic. +* [**Localization**](localization.md) - Support multiple languages and regional formats. + +## Getting Started + +To start using the SfDataGrid widget in your Flutter application, refer to the [Getting Started with Flutter DataGrid](getting-started.md) documentation. + +## API Reference + +For a complete list of properties, methods, and events of the SfDataGrid widget, refer to the [SfDataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html). + +## Sample GitHub Repository + +You can download a complete working sample from the [GitHub repository](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid) to explore the SfDataGrid widget with various features implemented. diff --git a/Flutter/datagrid/paging.md b/Flutter/datagrid/paging.md index f3c4fb7e0..20ddafb5f 100644 --- a/Flutter/datagrid/paging.md +++ b/Flutter/datagrid/paging.md @@ -14,11 +14,11 @@ The Datagrid interactively supports the manipulation of data using the [SfDataPa The Datagrid performs paging of data using the `SfDataPager`. To enable paging, follow this procedure * Create a new `SfDataPager` widget, and set the [SfDataGrid.DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) to the [SfDataPager.delegate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/delegate.html) property. -* Set the number of pages required to be displayed in the data pager by setting the [SfDataPager.pageCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageCount.html) property. +* Set the number of pages required to be displayed in the data pager by setting the [SfDataPager.pageCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageCount.html) property. This is calculated as the total row count divided by rows per page, then rounded up. * Set the number of buttons that should be displayed in view by setting the [SfDataPager.visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html) property. -* Load the data for a specific page in the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method. This method is called for every page navigation from the data pager. +* Load the data for a specific page in the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method. This method returns a `Future` and is called when navigating between pages in the data pager. -N> The `SfDataPager.visibleItemsCount` property default value is 5. +N> The `SfDataPager.visibleItemsCount` property default value is 5. Also, ensure that the [syncfusion_flutter_datagrid](https://pub.dev/packages/syncfusion_flutter_datagrid) and [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) packages are added to your `pubspec.yaml` file. The following code example illustrates using the `SfDataPager` with the Datagrid control: @@ -26,12 +26,35 @@ The following code example illustrates using the `SfDataPager` with the Datagrid {% highlight Dart %} import 'package:intl/intl.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + +// OrderInfo model class +class OrderInfo { + OrderInfo({ + required this.orderID, + required this.customerID, + required this.orderDate, + required this.freight, + }); + + final int orderID; + final String customerID; + final DateTime orderDate; + final double freight; +} final int _rowsPerPage = 15; final double _dataPagerHeight = 60.0; - List _orders = []; - List _paginatedOrders = []; - final OrderInfoDataSource _orderInfoDataSource = OrderInfoDataSource(); + List _orders = []; // Populate with sample data + List _paginatedOrders = []; + late final OrderInfoDataSource _orderInfoDataSource; + + @override + void initState() { + super.initState(); + // Initialize the data source after populating _orders + _orderInfoDataSource = OrderInfoDataSource(); + } @override Widget build(BuildContext context) { @@ -45,7 +68,7 @@ import 'package:intl/intl.dart'; height: _dataPagerHeight, child: SfDataPager( delegate: _orderInfoDataSource, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, )) ]); @@ -98,7 +121,8 @@ import 'package:intl/intl.dart'; class OrderInfoDataSource extends DataGridSource { OrderInfoDataSource() { - _paginatedOrders = _orders.getRange(0, 19).toList(growable: false); + int endIndex = _orders.length < _rowsPerPage ? _orders.length : _rowsPerPage; + _paginatedOrders = _orders.getRange(0, endIndex).toList(growable: false); buildPaginatedDataGridRows(); } @@ -183,52 +207,13 @@ class OrderInfoDataSource extends DataGridSource { ![flutter datapager with datagrid](images/paging/flutter-datapager.png) -## Callbacks - -The SfDataPager provides the [onPageNavigationStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationStart.html) and [onPageNavigationEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationEnd.html) callbacks to listen to the page navigation at the widget level. - -Typically, these callbacks are used to show and hide the loading indicator. - -{% tabs %} -{% highlight Dart %} - - @override - Widget build(BuildContext context) { - return Scaffold(body: LayoutBuilder(builder: (context, constraints) { - return Row(children: [ - Column(children: [ - SizedBox( - height: constraints.maxHeight - 60, - width: constraints.maxWidth, - child: _buildDataGrid(constraints)), - Container( - height: 60, - width: constraints.maxWidth, - child: SfDataPager( - pageCount: _orders.length / _rowsPerPage, - direction: Axis.horizontal, - onPageNavigationStart: (int pageIndex) { - //You can do your customization - }, - delegate: _orderInfoDataSource, - onPageNavigationEnd: (int pageIndex) { - //You can do your customization - })) - ]) - ]); - })); - } - -{% endhighlight %} -{% endtabs %} - ## Asynchronous data loading You can load the data asynchronously to the `SfDataPager` by overriding the `handlePageChange` method and await the method while loading the data. -You can use `onPageNavigationStart` and `onPageNavigationEnd` callbacks to show and hide the loading indicator when navigating between pages. +The [onPageNavigationStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationStart.html) and [onPageNavigationEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationEnd.html) callbacks can be used to show and hide the loading indicator when navigating between pages. -In the below example, we have set await for 2000ms and displayed the loading indicator until 2000ms. +In the following example, a 2000ms delay is used to simulate asynchronous data loading. Replace this with an actual API call or database query in your application. {% tabs %} {% highlight Dart %} @@ -295,7 +280,8 @@ import 'package:intl/intl.dart'; class OrderInfoDataSource extends DataGridSource { OrderInfoDataSource() { - _paginatedOrders = _orders.getRange(0, 19).toList(growable: false); + int endIndex = _orders.length < _rowsPerPage ? _orders.length : _rowsPerPage; + _paginatedOrders = _orders.getRange(0, endIndex).toList(growable: false); buildPaginatedDataGridRows(); } @@ -352,6 +338,7 @@ class OrderInfoDataSource extends DataGridSource { int startIndex = newPageIndex * _rowsPerPage; int endIndex = startIndex + _rowsPerPage; if (startIndex < _orders.length && endIndex <= _orders.length) { + // Simulate asynchronous data loading (replace with actual API call) await Future.delayed(Duration(milliseconds: 2000)); _paginatedOrders = _orders.getRange(startIndex, endIndex).toList(growable: false); @@ -387,29 +374,39 @@ class OrderInfoDataSource extends DataGridSource { ## Programmatic page navigation -The `SfDataPager` provides the support to navigate between the pages programmatically using a [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) with the following options. +The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) provides the support to navigate between the pages programmatically using a [DataPagerController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController-class.html) with the following options. -* [nextPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/nextPage.html) -* [previousPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/previousPage.html) -* [LastPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/lastPage.html) -* [firstPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/firstPage.html) +* [nextPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/nextPage.html) — Navigate to the next page +* [previousPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/previousPage.html) — Navigate to the previous page +* [lastPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/lastPage.html) — Navigate to the last page +* [firstPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/firstPage.html) — Navigate to the first page -The following code example shows how to navigate the previous page programmatically, +The following code example shows how to navigate the previous page programmatically: {% tabs %} {% highlight Dart %} - DataPagerController _controller = DataPagerController(); +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + + late DataPagerController _controller; + late OrderInfoDataSource _orderInfoDataSource; + + @override + void initState() { + super.initState(); + _controller = DataPagerController(); + _orderInfoDataSource = OrderInfoDataSource(); + } @override Widget build(BuildContext context) { return Scaffold(body: LayoutBuilder(builder: (context, constraint) { return Column(children: [ - MaterialButton( + ElevatedButton( onPressed: () { _controller.previousPage(); }, - child: Text('Move Previous page'), + child: const Text('Move to Previous Page'), ), SizedBox( height: constraint.maxHeight - 120, @@ -421,9 +418,9 @@ The following code example shows how to navigate the previous page programmatica alignment: Alignment.center, child: SfDataPager( delegate: _orderInfoDataSource, - initialPageIndex: 2, + initialPageIndex: 0, controller: _controller, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, ))) ]); @@ -435,21 +432,50 @@ The following code example shows how to navigate the previous page programmatica ## Show dropdown button to choose rows per page -Show the dropdown button option to select a different number of rows per page by defining the [onRowPerPageChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onRowsPerPageChanged.html) callback. If it is null, no option will be provided to select a different number of rows per page. +Show the dropdown button option to select a different number of rows per page by defining the [onRowsPerPageChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onRowsPerPageChanged.html) callback. If it is null, no option will be provided to select a different number of rows per page. -Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/availableRowsPerPage.html) property to define the list of numbers to be displayed in the drop-down. The default value of the `availableRowsPerPage` property is [10,15,20]. +Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/availableRowsPerPage.html) property to define the list of numbers to be displayed in the drop-down. The default value of the `availableRowsPerPage` property is [10, 15, 20]. >**NOTE** - You can view dropdown button option by horizontally scrolling the DataPager. The dropdown button option is not supported, if the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) is vertical. + You can view the dropdown button option by horizontally scrolling the DataPager. The dropdown button option is not supported if the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) is vertical. Also, only values that are present in the `availableRowsPerPage` list can be selected from the dropdown. {% tabs %} {% highlight Dart %} - int _rowsPerPage=10; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + +// Employee model class +class Employee { + Employee({ + required this.id, + required this.name, + required this.designation, + required this.salary, + }); + + final int id; + final String name; + final String designation; + final int salary; +} + + int _rowsPerPage = 10; List employees = []; late EmployeeDataSource employeeDataSource; double datapagerHeight = 70.0; + // Sample data generation + List getEmployeeData() { + return [ + Employee(id: 1001, name: 'James', designation: 'Project Lead', salary: 20000), + Employee(id: 1002, name: 'Kathryn', designation: 'Manager', salary: 30000), + Employee(id: 1003, name: 'Lara', designation: 'Developer', salary: 15000), + Employee(id: 1004, name: 'Michael', designation: 'Developer', salary: 15000), + Employee(id: 1005, name: 'Martin', designation: 'Developer', salary: 15000), + // Add more employee records as needed + ]; + } + @override void initState() { super.initState(); @@ -563,30 +589,30 @@ Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_ ## Orientation -`SfDataPager` allows you to arrange the child elements either horizontally or vertically. This can be achieved by using the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) Property. `direction` is an Enum type. +The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) allows you to arrange the child elements either horizontally or vertically. This can be achieved by using the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) property, which accepts `Axis.horizontal` or `Axis.vertical`.
-Enum +Value Description
-horizontal +Axis.horizontal -This is the default enum value for direction. Arranges all the navigation buttons and numeric buttons horizontally.{{'![flutter datapager in horizontal direction](images/paging/flutter-datapager-direction-horizontal.png)'|markdownify}} +Default value. Arranges all the navigation buttons and numeric page buttons horizontally.{{'![flutter datapager in horizontal direction](images/paging/flutter-datapager-direction-horizontal.png)'|markdownify}}
-vertical +Axis.vertical -Arranges all the navigation buttons and numeric buttons vertically by setting Axis.vertical to direction property.{{'![flutter datapager in vertical direction](images/paging/flutter-datapager-direction-vertical.png)'|markdownify}} +Arranges all the navigation buttons and numeric page buttons vertically.{{'![flutter datapager in vertical direction](images/paging/flutter-datapager-direction-vertical.png)'|markdownify}}
@@ -594,9 +620,9 @@ Arranges all the navigation buttons and numeric buttons vertically by setting Ax ## Appearance -SfDataPager allows customizing the appearance of the data pager using the [SfDataPagerThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerThemeData-class.html) in [SfDataPagerTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerTheme-class.html). The `SfDataPager` should be wrapped inside the `SfDataPagerTheme.` +The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) allows customizing the appearance using the [SfDataPagerThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerThemeData-class.html) in [SfDataPagerTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerTheme-class.html). The `SfDataPager` should be wrapped inside the `SfDataPagerTheme` widget. -Import the following class from the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. +Import the following class from the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package: {% tabs %} {% highlight Dart %} @@ -659,11 +685,11 @@ The padding between the page items including navigation page items such as first {% endhighlight %} {% endtabs %} -N> The default value of `SfDataPager.itemPadding` is 5.0. +**Note:** The default value of `SfDataPager.itemPadding` is 5.0. ### Set the height and width of the page items -The default width and height of the page items are 50 and 50, respectively. For changing page number items size, use the [itemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemWidth.html) and [itemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemHeight.html) properties; for changing navigation items size such as first, last, previous, and next, use the [navigationItemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemHeight.html) and [navigationItemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemWidth.html) properties. +The default width and height of the page items are 50 and 50, respectively. To change the size of page number items, use the [itemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemWidth.html) and [itemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemHeight.html) properties. To change the size of navigation items (first, last, previous, and next), use the [navigationItemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemHeight.html) and [navigationItemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemWidth.html) properties. {% tabs %} {% highlight Dart %} @@ -707,7 +733,7 @@ To hide certain navigation page items, use the following properties: * [nextPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/nextPageItemVisible.html) * [previousPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/previousPageItemVisible.html) - N> Default value of all properties is true. +**Note:** The default value of all these properties is `true`. {% tabs %} {% highlight Dart %} @@ -840,9 +866,9 @@ Load any widget to the page button by using the [SfDataPager.pageItemBuilder](ht ## Sort all the rows instead of rows available on a page -By default, the rows on a page are sorted. To sort all the rows available for paging, do not override the `handlePageChange` method in the `DataGridSource` class. The DataGrid will automatically split the rows required for each page based on the `SfDataPager.pageCount`, i.e. the divided value of the [DataGridRows.rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) and `SfDataPager.pageCount`. +By default, when the `handlePageChange` method is overridden in the `DataGridSource` class, sorting is applied only to the rows available on the current page. To sort all rows available for paging, do not override the `handlePageChange` method. In this case, the DataGrid will automatically split the rows required for each page based on the `SfDataPager.pageCount` after sorting all rows. -If you want to specifically maintain the rows required for a page, you can use the [SfDataGrid.rowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsPerPage.html) property. However, make sure that you do not override the `handlePageChange` method in the `DataGridSource` class at the sample level. +Alternatively, if you want to use automatic pagination with sorting, use the [SfDataGrid.rowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsPerPage.html) property instead of manually handling pagination. With this approach, do not override the `handlePageChange` method, and the DataGrid will manage pagination automatically while applying sorting to all rows. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/placeholder.md b/Flutter/datagrid/placeholder.md index 597fc7f38..9ff7b3fea 100644 --- a/Flutter/datagrid/placeholder.md +++ b/Flutter/datagrid/placeholder.md @@ -7,9 +7,11 @@ control: SfDataGrid documentation: ug --- -# Placeholder in Flutter Datagrid (SfDataGrid) +# Placeholder in Flutter DataGrid (SfDataGrid) -The `SfDataGrid` provides built-in support for displaying a placeholder when the data source is empty by setting the [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) property. When the `SfDataGrid.placeholder` is set, the DataGrid automatically shows the specified widget in the scroll view area. By default, the `SfDataGrid` does not display anything when the data source is empty. +The `SfDataGrid` provides built-in support for displaying a placeholder when the data source is empty by setting the [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) property. The `placeholder` property accepts a `Widget` that will be displayed in the scroll view area when the DataGrid has no data to show. + +N> **Note:** Ensure you have implemented a [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) class and configured [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) objects before implementing the placeholder feature. For detailed setup instructions, refer to the [Getting Started with SfDataGrid](getting-started.md) documentation. The following example shows how to add a `placeholder` in SfDataGrid: @@ -23,7 +25,7 @@ The following example shows how to add a `placeholder` in SfDataGrid: title: const Text('Syncfusion Flutter DataGrid'), ), body: SfDataGrid( - source: employeeDataSource, + source: _employeeDataSource, columnWidthMode: ColumnWidthMode.auto, columns: [ GridColumn( @@ -83,3 +85,26 @@ The following example shows how to add a `placeholder` in SfDataGrid: {% endtabs %} Flutter DataGrid displays a placeholder when there are no rows + +**Behavior** + +The placeholder widget is automatically displayed when: +- The data source is empty (contains no rows) +- The `SfDataGrid.placeholder` property is assigned + +The placeholder is automatically hidden when: +- Data is added to the data source +- Rows become available in the DataGrid + +**API Reference** + +* [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) — Gets or sets the widget to display when the DataGrid is empty. +* [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — The data source for populating the DataGrid. + +**See Also** + +* [Getting Started with SfDataGrid](getting-started.md) +* [Styling DataGrid Cells](styles.md) +* [DataGrid Column Types](column-types.md) + +N> **Sample applications** — Refer to the [DataGrid placeholder sample](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid) in the Syncfusion Flutter Examples repository for a complete working implementation. diff --git a/Flutter/datagrid/pull-to-refresh.md b/Flutter/datagrid/pull-to-refresh.md index 574d6f247..e6de30aec 100644 --- a/Flutter/datagrid/pull-to-refresh.md +++ b/Flutter/datagrid/pull-to-refresh.md @@ -9,15 +9,44 @@ documentation: ug # Pull to Refresh in Flutter DataGrid (SfDataGrid) -The Flutter DataTable provides support to add more data at runtime by using the PullToRefresh feature. -You can simply enable the PullToRefresh option by setting the [SfDataGrid.allowPullToRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowPullToRefresh.html) property to `true` and override the [DataGridSource.handleRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleRefresh.html) method to include the data which is going to add to the data source at runtime and then notify the data grid about the changes. +The SfDataGrid provides support to add more data at runtime by using the pull-to-refresh feature. You can enable the pull-to-refresh option by setting the [SfDataGrid.allowPullToRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowPullToRefresh.html) property to `true` and overriding the [DataGridSource.handleRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleRefresh.html) method to add new data to the data source at runtime, then notify the data grid about the changes. + +> **Note:** This feature requires the `syncfusion_flutter_datagrid` package. Ensure you have added it to your `pubspec.yaml` file. Pull-to-refresh is supported on Flutter 2.0 and above. {% tabs %} {% highlight Dart %} +import 'dart:math'; +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - EmployeeDataSource _employeeDataSource = EmployeeDataSource(); +class Employee { + final int id; + final String name; + final String designation; + final int salary; + + Employee( + this.id, + this.name, + this.designation, + this.salary, + ); +} + +class PullToRefreshDemo extends StatefulWidget { + @override + State createState() => _PullToRefreshDemoState(); +} + +class _PullToRefreshDemoState extends State { + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(); + } @override Widget build(BuildContext context) { @@ -64,12 +93,27 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ], ); } +} class EmployeeDataSource extends DataGridSource { + late List _employees = []; + EmployeeDataSource() { + _initializeEmployees(); buildDataGridRows(); } + void _initializeEmployees() { + _employees = [ + Employee(1001, 'Welli', 'Project Lead', 20000), + Employee(1002, 'Blonp', 'Developer', 18000), + Employee(1003, 'Folko', 'Manager', 22000), + Employee(1004, 'Furip', 'Designer', 17000), + Employee(1005, 'Folig', 'System Analyst', 19000), + Employee(1006, 'Picco', 'CEO', 30000), + ]; + } + List dataGridRows = []; @override @@ -94,7 +138,8 @@ class EmployeeDataSource extends DataGridSource { @override Future handleRefresh() async { - await Future.delayed(Duration(seconds: 5)); + // Simulate network delay for fetching new data from server + await Future.delayed(Duration(seconds: 2)); _addMoreRows(_employees, 15); buildDataGridRows(); notifyListeners(); @@ -114,15 +159,15 @@ class EmployeeDataSource extends DataGridSource { } void _addMoreRows(List employees, int count) { - final Random _random = Random(); - final startIndex = employees.isNotEmpty ? employees.length : 0, - endIndex = startIndex + count; + final Random random = Random(); + final startIndex = employees.isNotEmpty ? employees.length : 0; + final endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { employees.add(Employee( 1000 + i, - _names[_random.nextInt(_names.length - 1)], - _designation[_random.nextInt(_designation.length - 1)], - 10000 + _random.nextInt(10000), + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), )); } } @@ -164,23 +209,41 @@ Download the demo application from [GitHub](https://github.com/SyncfusionExample ## Customizing the refresh indicator -SfDataGrid displays the [RefreshIndicator](https://api.flutter.dev/flutter/material/RefreshIndicator-class.html) for `pull to refresh` action. So, set the color and background color of the refresh indicator by using the [ThemeData.accentColor](https://api.flutter.dev/flutter/material/ThemeData/accentColor.html) and [ThemeData.canvasColor](https://api.flutter.dev/flutter/material/ThemeData/canvasColor.html) properties. +SfDataGrid displays Flutter's [RefreshIndicator](https://api.flutter.dev/flutter/material/RefreshIndicator-class.html) during pull-to-refresh actions. You can customize the refresh indicator by using the [SfDataGrid.refreshIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/refreshIndicatorStrokeWidth.html) and [SfDataGrid.refreshIndicatorDisplacement](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/refreshIndicatorDisplacement.html) properties. -Also, change the stroke width and displacement of the refresh indicator by using the [SfDataGrid.refreshIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/refreshIndicatorStrokeWidth.html) and [SfDataGrid.refreshIndicatorDisplacement](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/refreshIndicatorDisplacement.html) properties. +To set the indicator's color and background color, use the [ColorScheme](https://api.flutter.dev/flutter/material/ColorScheme-class.html) properties within [ThemeData](https://api.flutter.dev/flutter/material/ThemeData-class.html). The `primary` color in ColorScheme controls the indicator's color. + +> **Note:** The deprecated `ThemeData.accentColor` property has been replaced with `ColorScheme.primary` in Flutter 3.0+. Use ColorScheme for modern Flutter applications. {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +class CustomRefreshIndicatorDemo extends StatefulWidget { + @override + State createState() => _CustomRefreshIndicatorDemoState(); +} + +class _CustomRefreshIndicatorDemoState extends State { + late EmployeeDataSource _employeeDataSource; + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(); + } + @override Widget build(BuildContext context) { return Theme( data: ThemeData( brightness: Brightness.light, - canvasColor: Colors.lightBlue, + scaffoldBackgroundColor: Colors.white, colorScheme: const ColorScheme.light( - primary: Colors.white)), + primary: Colors.blue, + surface: Colors.lightBlue)), child: SfDataGrid( allowPullToRefresh: true, source: _employeeDataSource, @@ -225,6 +288,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ))), ])); } +} {% endhighlight %} {% endtabs %} @@ -235,20 +299,60 @@ Download the demo application from [GitHub](https://github.com/SyncfusionExample ## Programmatic Pull to Refresh -If you want to refresh data without showing a refresh indicator, pass `false` to the `showRefreshIndicator` optional parameter of the [refresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState/refresh.html) method. By doing this, the `DataGridSource.handleRefresh` method will be called without showing the `RefreshIndicator` in UI. +You can trigger data refresh programmatically using the [SfDataGridState.refresh()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState/refresh.html) method. By default, the refresh indicator is displayed during the refresh operation. To refresh data without showing the refresh indicator, pass `false` to the `showRefreshIndicator` parameter. + +The `refresh()` method calls the [DataGridSource.handleRefresh()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleRefresh.html) method, which is a `Future` that returns when the refresh operation completes. If an exception occurs during `handleRefresh()`, the data grid will handle it gracefully and the refresh state will be reset. + +> **Note:** Use a `GlobalKey` to access the refresh method from outside the SfDataGrid widget. {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - final GlobalKey key = GlobalKey(); +class ProgrammaticRefreshDemo extends StatefulWidget { + @override + State createState() => _ProgrammaticRefreshDemoState(); +} + +class _ProgrammaticRefreshDemoState extends State { + late EmployeeDataSource _employeeDataSource; + final GlobalKey _dataGridKey = GlobalKey(); + + @override + void initState() { + super.initState(); + _employeeDataSource = EmployeeDataSource(); + } + + Future _onRefreshPressed() async { + try { + // Refresh with indicator + await _dataGridKey.currentState!.refresh(); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error refreshing data: $e')), + ); + } + } + + Future _onSilentRefreshPressed() async { + try { + // Refresh without showing indicator + await _dataGridKey.currentState!.refresh(showRefreshIndicator: false); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error refreshing data: $e')), + ); + } + } @override Widget build(BuildContext context) { return Scaffold( body: SfDataGrid( - key: key, + key: _dataGridKey, allowPullToRefresh: true, source: _employeeDataSource, columns: [ @@ -290,12 +394,22 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ))), ], ), - floatingActionButton: FloatingActionButton( - child: Icon(Icons.refresh), - onPressed: () { - key.currentState!.refresh(); - })); + floatingActionButton: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + FloatingActionButton( + heroTag: 'refresh_with_indicator', + child: Icon(Icons.refresh), + onPressed: _onRefreshPressed), + SizedBox(height: 10), + FloatingActionButton( + heroTag: 'refresh_without_indicator', + child: Icon(Icons.cloud_download), + onPressed: _onSilentRefreshPressed), + ], + )); } +} {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/right-to-left.md b/Flutter/datagrid/right-to-left.md index 249d7f762..c52d3b6a8 100644 --- a/Flutter/datagrid/right-to-left.md +++ b/Flutter/datagrid/right-to-left.md @@ -9,7 +9,9 @@ documentation: ug # Right to Left (RTL) in Flutter DataGrid (SfDataGrid) -SfDataGrid supports right-to-left rendering. The columns will be rendered based on LTR and RTL direction. +SfDataGrid supports right-to-left (RTL) rendering. When RTL is enabled, columns will be rendered in reverse order, scrollbars will appear on the left side, and text alignment will be mirrored accordingly. + +> **Note:** This feature requires Flutter 2.0+ and syncfusion_flutter_datagrid 19.1.0 or later. ## RTL rendering ways @@ -17,7 +19,7 @@ Right-to-left rendering can be switched in the following ways: ### Wrapping the SfDataGrid with the Directionality widget -To change the rendering direction from right to left, wrap the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget inside the [Directionality](https://api.flutter.dev/flutter/widgets/Directionality-class.html) widget and set the [textDirection](https://api.flutter.dev/flutter/widgets/Directionality/textDirection.html) property as [TextDirection.rtl](https://api.flutter.dev/flutter/dart-ui/TextDirection-class.html). +Wrap the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget inside the [Directionality](https://api.flutter.dev/flutter/widgets/Directionality-class.html) widget and set the [textDirection](https://api.flutter.dev/flutter/widgets/Directionality/textDirection.html) property to [TextDirection.rtl](https://api.flutter.dev/flutter/dart-ui/TextDirection-class.html) to enable RTL rendering. {% tabs %} {% highlight Dart %} @@ -69,19 +71,19 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ### Changing the locale to RTL languages -To change the Datagrid rendering direction from right to left, change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) to any of the RTL languages such as Arabic, Persian, Hebrew, Pashto, and Urdu. - -To use `flutter_localizations`, add the package as a dependency to `pubspec.yaml` file. - -{% highlight dart %} +Change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) property of [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html) to an RTL language such as Arabic (ar), Persian (fa), Hebrew (he), Pashto (ps), or Urdu (ur) to enable RTL rendering. -dependencies: -flutter_localizations: - sdk: flutter - -{% endhighlight %} +> **Note:** The `flutter_localizations` package is required. Add it to your `pubspec.yaml` file: +> +> ```dart +> dependencies: +> flutter_localizations: +> sdk: flutter +> ``` +> +> Then run `flutter pub get` to download the package. -Then, import the `flutter_localizations` library, specify [localizationsDelegates](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) and `supportedLocales` for `MaterialApp`. +Import the `flutter_localizations` library and configure [localizationsDelegates](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) and `supportedLocales` in your `MaterialApp`. {% tabs %} {% highlight Dart %} @@ -89,6 +91,13 @@ Then, import the `flutter_localizations` library, specify [localizationsDelegate import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({Key? key}) : super(key: key); + @override Widget build(BuildContext context) { return MaterialApp( @@ -99,44 +108,51 @@ import 'package:flutter_localizations/flutter_localizations.dart'; supportedLocales: [ Locale('en'), Locale('ar'), - // ... other locales the app supports + Locale('fa'), + Locale('he'), + Locale('ps'), + Locale('ur'), ], locale: Locale('ar'), - home: SfDataGrid( - source: _employeeDataSource, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text( - 'ID', - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ])); + home: Scaffold( + appBar: AppBar( + title: Text('RTL DataGrid'), + ), + body: SfDataGrid( + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'))), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'))), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'))), + ]), + )); } +} {% endhighlight %} {% endtabs %} \ No newline at end of file diff --git a/Flutter/datagrid/row-height-customization.md b/Flutter/datagrid/row-height-customization.md index 4e58cb3d9..3a5242839 100644 --- a/Flutter/datagrid/row-height-customization.md +++ b/Flutter/datagrid/row-height-customization.md @@ -11,6 +11,8 @@ documentation: ug This section explains options to customize the header row height and the row height of all the grid rows or particular rows based on your requirements. +> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` + ## Set the height for a specific row The row height of a particular row can be set by using the [SfDataGrid.onQueryRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onQueryRowHeight.html) callback. @@ -128,13 +130,13 @@ The row height can be autofit based on its content in the `SfDataGrid.onQueryRow {% endhighlight %} {% endtabs %} -![flutter datagrid shows autofit the row height based on content](images/row-height-customization/flutter-datagrid-autofit-rows.png) +![flutter datagrid shows auto-fitting the row height based on content](images/row-height-customization/flutter-datagrid-autofit-rows.png) -The `RowHeightDetails.getIntrinsicRowHeight` method provides some properties to customize the autofit calculation, +The [RowHeightDetails.getIntrinsicRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowHeightDetails/getIntrinsicRowHeight.html) method provides some properties to customize the autofit calculation: -* `excludeColumns` – By default, the `getIntrinsicRowHeight` method calculates the row height based on all columns. To skip the specific columns from the row height calculation, add that column's [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) to the `excludeColumns` collection. +* `excludedColumns` – By default, the `getIntrinsicRowHeight` method calculates the row height based on all columns. To skip specific columns from the row height calculation, add that column's [GridColumn.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) to the `excludedColumns` collection. -* `canIncludeHiddenColumns` – The hidden columns ([GridColumn.visible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/visible.html) is false) can also be considered for the row height calculation by setting the `canIncludeHiddenColumns` as true. +* `canIncludeHiddenColumns` – The hidden columns ([GridColumn.visible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/visible.html) is `false`) can also be considered for the row height calculation by setting `canIncludeHiddenColumns` to `true`. {% tabs %} {% highlight dart %} @@ -334,25 +336,26 @@ class CustomColumnSizer extends ColumnSizer { {% endhighlight %} {% endtabs %} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-different-text-style-in-Flutter-DataTable-sfdatagrid). +> **NOTE:** The `CustomColumnSizer` is a custom class that should be added to your dart file. You can download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-different-text-style-in-Flutter-DataTable-sfdatagrid). -![flutter datagrid shows autofit the row height based on different text style](images/row-height-customization/flutter-datagrid-autofit-textstyle-customization.png) +![flutter datagrid shows auto-fitting the row height based on different text style](images/row-height-customization/flutter-datagrid-autofit-textstyle-customization.png) ## Fit the row based on the formatted value -By default, the cell height is calculated based on the `DataGridCell.value` property. To autofit the cell height based on the displayed formatted value (this is, DateFormat and NumberFormat), simply override the `computeCellHeight` method and return the super method with the required `cellValue.` +By default, the cell height is calculated based on the `DataGridCell.value` property. To autofit the cell height based on the displayed formatted value (such as DateFormat and NumberFormat), simply override the `computeCellHeight` method and return the super method with the required `cellValue`. -To use `intl`, add the package as a dependency to the `pubspec.yaml` file. +To use date and number formatting, add the `intl` package as a dependency to the `pubspec.yaml` file. {% highlight dart %} dependencies: - intl: ^0.17.0 + intl: ^0.19.0 {% endhighlight %} -Import the `intl` library, to use the date and number format. +> **NOTE:** Requires Flutter 2.0 or later and Dart 2.12 or later. The `intl` package provides internationalized message support for Dart and Flutter applications. + +Import the required packages: {% tabs %} {% highlight dart %} @@ -484,15 +487,16 @@ class CustomColumnSizer extends ColumnSizer { {% endhighlight %} {% endtabs %} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-formatted-value-in-Flutter-datatable-sfdatagrid). +> **NOTE:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-formatted-value-in-Flutter-datatable-sfdatagrid). -![flutter datagrid shows autofit the row height based on formatted cell value](images/row-height-customization/flutter-datagrid-formatted-cellvalue.png) +![flutter datagrid shows auto-fitting the row height based on formatted cell value](images/row-height-customization/flutter-datagrid-formatted-cellvalue.png) ## Set height for the header row [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows you to customize the height of the header row by using the [headerRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerRowHeight.html) property. +> **NOTE:** The default value of `headerRowHeight` is `49.0`. You can set any double value to customize the header row height according to your requirements. + {% tabs %} {% highlight dart %} @@ -552,6 +556,8 @@ class CustomColumnSizer extends ColumnSizer { You can customize the height of the grid rows in `SfDataGrid` by using the [rowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowHeight.html) property. +> **NOTE:** The default value of `rowHeight` is `49.0`. Use this property to set a uniform height for all data rows (excluding the header row). For variable heights based on content, use the `onQueryRowHeight` callback instead. + {% tabs %} {% highlight Dart %} @@ -613,18 +619,19 @@ The `SfDataGrid` allows you to update or refresh a specific row and its height w Refresh a specific row and its height by using the [DataGridController.refreshRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/refreshRow.html) method. This method has the following two arguments: -* **rowIndex**- Specify the required row index which is required to refresh. If you specify this, the data alone will be refreshed for a row. +* **rowIndex** - Specify the row index to refresh. If you specify this alone, only the data will be refreshed for that row. -* **recalculateRowHeight** - Decides whether a height of a row should be refreshed along with the data. +* **recalculateRowHeight** - Determines whether the row height should be recalculated along with the data refresh. -If you call the `refreshRow` method, the `onQueryRowHeight` callback will be called for that specific row. So, auto-calculation of height can be recalculated for that row. +When you call the `refreshRow` method, the `onQueryRowHeight` callback will be invoked for that specific row, allowing auto-height calculation to be recalculated. -In the below example, row data is updated when the `refreshRow` is called in the `onPressed` callback of the `TextButton.` +> **NOTE:** When calling `refreshRow`, ensure the rowIndex is within the valid range (0 to dataGridRows.length - 1). Calling with an out-of-bounds rowIndex may not refresh the intended row. Use `recalculateRowHeight: true` to recalculate row heights based on updated content. + +In the following example, row data is updated when `refreshRow` is called in the `onPressed` callback of the `TextButton`: {% tabs %} {% highlight Dart %} - List _employees = []; late EmployeeDataSource _employeeDataSource; final DataGridController _controller = DataGridController(); List _employees = []; @@ -755,12 +762,11 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -In the following example, the row data is refreshed along with its row height when the `refreshRow` is called in the `onPressed` callback of the `TextButton.` +In the following example, the row data is refreshed along with its row height when `refreshRow` is called with `recalculateRowHeight: true` in the `onPressed` callback of the `TextButton`: {% tabs %} {% highlight Dart %} - List _employees = []; late EmployeeDataSource _employeeDataSource; final DataGridController _controller = DataGridController(); List _employees = []; @@ -844,5 +850,50 @@ In the following example, the row data is refreshed along with its row height wh ])); } +class EmployeeDataSource extends DataGridSource { + EmployeeDataSource({required List employees}) { + buildDataGridSource(employees); + } + + void buildDataGridSource(List employees) { + dataGridRows = employees + .map((dataGridRow) => DataGridRow(cells: [ + DataGridCell(columnName: 'id', value: dataGridRow.id), + DataGridCell(columnName: 'name', value: dataGridRow.name), + DataGridCell( + columnName: 'designation', value: dataGridRow.designation), + DataGridCell( + columnName: 'salary', value: dataGridRow.salary), + ])) + .toList(); + } + + List dataGridRows = []; + + @override + List get rows => dataGridRows; + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: (dataGridCell.columnName == 'id' || + dataGridCell.columnName == 'salary') + ? Alignment.centerRight + : Alignment.centerLeft, + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + dataGridCell.value.toString(), + overflow: TextOverflow.ellipsis, + )); + }).toList()); + } + + void updateDataGridSource() { + notifyListeners(); + } +} + {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/scrolling.md b/Flutter/datagrid/scrolling.md index 4fec6a5fd..98a26b6b8 100644 --- a/Flutter/datagrid/scrolling.md +++ b/Flutter/datagrid/scrolling.md @@ -13,9 +13,9 @@ SfDataGrid provides support to scroll the content in both horizontal and vertica ## Show Scrollbars always -You can show horizontal and vertical scrollbars always by using the [SfDataGrid.isScrollbarAlwaysShown](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/isScrollbarAlwaysShown.html) property. When the `isScrollbarAlwaysShown` is set to false, the scrollbar will be shown during scrolling and will fade out otherwise. When it is true, the scrollbar will always be visible and never fade out even after the scrolling. +You can show horizontal and vertical scrollbars always by using the [SfDataGrid.isScrollbarAlwaysShown](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/isScrollbarAlwaysShown.html) property. When the `isScrollbarAlwaysShown` is set to `false`, the scrollbar will be shown during scrolling and will fade out otherwise. When it is `true`, the scrollbar will always be visible and never fade out even after scrolling. -N> The default value of `isScrollbarAlwaysShown` is false. +> **NOTE:** The default value of `isScrollbarAlwaysShown` is `false`. This ensures scrollbars appear only during active scrolling for a cleaner UI. {% tabs %} {% highlight Dart %} @@ -71,9 +71,9 @@ N> The default value of `isScrollbarAlwaysShown` is false. ## Change scrollbars visibility -You can control the visibility of horizontal and vertical scrollbars in the DataGrid by setting the [SfDataGrid.showVerticalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showVerticalScrollbar.html) and [SfDataGrid.showHorizontalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showHorizontalScrollbar.html) properties. To disable the default scrollbar of the `SingleChildScrollView`, wrap the `ScrollConfiguration` as the parent for the `SfDataGrid` and set the scrollbars to false. +You can control the visibility of horizontal and vertical scrollbars in the DataGrid by setting the [SfDataGrid.showVerticalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showVerticalScrollbar.html) and [SfDataGrid.showHorizontalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showHorizontalScrollbar.html) properties. To disable the default scrollbar of the `SingleChildScrollView`, wrap the `ScrollConfiguration` as the parent for the `SfDataGrid` and set the scrollbars to `false`. This prevents duplicate scrollbars from appearing. -N> The default value of `showVerticalScrollbar` and `showHorizontalScrollbar` is true. +> **NOTE:** The default value of `showVerticalScrollbar` and `showHorizontalScrollbar` is `true`. Setting these to `false` disables only the DataGrid's internal scrollbars. The following code snippets demonstrate how to hide the scrollbars in the DataGrid: @@ -136,7 +136,7 @@ The following code snippets demonstrate how to hide the scrollbars in the DataGr SfDataGrid allows you to set the [ScrollPhysics](https://api.flutter.dev/flutter/widgets/ScrollPhysics-class.html) for horizontal and vertical scrollbars to control how the scroll view should respond to user input by using [horizontalScrollPhysics](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/horizontalScrollPhysics.html) and [verticalScrollPhysics](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/verticalScrollPhysics.html) properties respectively. -N> The default values of `horizontalScrollPhysics` and `verticalScrollPhysics` properties are `AlwaysScrollableScrollPhysics()`. +> **NOTE:** The default values of `horizontalScrollPhysics` and `verticalScrollPhysics` properties are `AlwaysScrollableScrollPhysics()`. The following example shows how to disable the horizontal and vertical scrolling by setting `NeverScrollableScrollPhysics()`. @@ -199,9 +199,11 @@ The Flutter DataTable provides support to scroll to a particular row and column ### Scroll to cell -Scroll programmatically to a particular cell can be achieved by passing the row and column index in the `scrollToCell` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in the `scrollToCell` method. +Scroll programmatically to a particular cell by passing the row and column index to the [DataGridController.scrollToCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToCell.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -N> The default value of `canAnimate` is `false`. +> **NOTE:** The default value of `canAnimate` is `false`. If you specify a rowIndex or columnIndex that exceeds the valid range, the scrolling will not occur. + +> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` {% tabs %} {% highlight Dart %} @@ -272,9 +274,9 @@ N> The default value of `canAnimate` is `false`. ### Scroll to row -Scroll programmatically to a particular row by passing the row index in the `scrollToRow` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in the `scrollToRow` method. +Scroll programmatically to a particular row by passing the row index to the [DataGridController.scrollToRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToRow.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -N> The default value of `canAnimate` is `false`. +> **NOTE:** The default value of `canAnimate` is `false`. If the specified rowIndex exceeds the total number of rows, the scrolling will not occur. {% tabs %} {% highlight Dart %} @@ -343,9 +345,9 @@ N> The default value of `canAnimate` is `false`. ### Scroll to column -Scroll programmatically to a particular column by passing the column index in the `scrollToColumn` method. SfDataGrid allows to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter in the `scrollToColumn` method. +Scroll programmatically to a particular column by passing the column index to the [DataGridController.scrollToColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToColumn.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -N> The default value of `canAnimate` is `false`. +> **NOTE:** The default value of `canAnimate` is `false`. If the specified columnIndex exceeds the total number of columns, the scrolling will not occur. {% tabs %} {% highlight Dart %} @@ -416,14 +418,14 @@ N> The default value of `canAnimate` is `false`. ### Scroll to the specific position -The `SfDataGrid` allows positioning of the scrolled row or column in view programmatically by passing the `DataGridScrollPosition` to `rowPosition` and `columnPosition` arguments respectively in `scrollToCell` and `position` argument of the `scrollToRow` and `scrollToColumn` methods. The following are the four types of positions available. +The `SfDataGrid` allows positioning of the scrolled row or column in view programmatically by passing the [DataGridScrollPosition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridScrollPosition.html) to `rowPosition` and `columnPosition` arguments respectively in `scrollToCell` and `position` argument of the `scrollToRow` and `scrollToColumn` methods. The following are the four types of positions available: -`makeVisible`: Scroll to make a specified row/column visible in Datagrid. If the specified row/column is already in view, scrolling will not occur. -`start`: Scroll to make the row/column positioned at the start of the Datagrid. -`center`: Scroll to make the row/column positioned at the center of the Datagrid. -`end`: Scroll to make the row/column positioned at the end of the Datagrid. +* `makeVisible` - Display the specified row/column if it is not already visible. If already in view, no scrolling occurs. +* `start` - Position the row/column at the start of the DataGrid. +* `center` - Position the row/column at the center of the DataGrid. +* `end` - Position the row/column at the end of the DataGrid. -N> The default value of `DataGridScrollPosition` is `Start`. +> **NOTE:** The default value of `DataGridScrollPosition` is `start`. {% tabs %} {% highlight Dart %} @@ -495,9 +497,9 @@ N> The default value of `DataGridScrollPosition` is `Start`. ### Scroll to the vertical offset -The Flutter DataTable supports scrolling programmatically to a particular vertical offset by passing the offset value to the `scrollToVerticalOffset` method. Also, it allows enabling the scrolling animation by passing `true` to the `canAnimate` parameter in the `scrollToVerticalOffset` method. +The Flutter DataTable supports scrolling programmatically to a particular vertical offset by passing the offset value to the [DataGridController.scrollToVerticalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToVerticalOffset.html) method. You can enable the scrolling animation by passing `true` to the `canAnimate` parameter. -N> The default value of `canAnimate` is `false`. +> **NOTE:** The default value of `canAnimate` is `false`. The offset value should be non-negative and not exceed the maximum scrollable extent. {% tabs %} {% highlight Dart %} @@ -566,9 +568,9 @@ N> The default value of `canAnimate` is `false`. ### Scroll to the horizontal offset -The Flutter DataTable supports scrolling programmatically to a particular horizontal offset by passing the offset value to the `scrollToHorizontalOffset` method. Also, it allows enabling the scrolling animation by passing `true` to the `canAnimate` parameter in the `scrollToHorizontalOffset` method. +The Flutter DataTable supports scrolling programmatically to a particular horizontal offset by passing the offset value to the [DataGridController.scrollToHorizontalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToHorizontalOffset.html) method. You can enable the scrolling animation by passing `true` to the `canAnimate` parameter. -N> The default value of `canAnimate` is `false`. +> **NOTE:** The default value of `canAnimate` is `false`. The offset value should be non-negative and not exceed the maximum scrollable extent. {% tabs %} {% highlight Dart %} @@ -635,21 +637,25 @@ N> The default value of `canAnimate` is `false`. {% endhighlight %} {% endtabs %} -N> The vertical and horizontal scrolled offset can be retrieved by using `DataGridController.verticalOffset` and `DataGridController.horizontalOffset` properties. +> **NOTE:** The vertical and horizontal scroll offsets can be retrieved using the [DataGridController.verticalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/verticalOffset.html) and [DataGridController.horizontalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/horizontalOffset.html) properties respectively. + +## Listen to scroll changes -## Listen the scroll changes +Listen to the vertical and horizontal scroll changes by using the [verticalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/verticalScrollController.html) and [horizontalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/horizontalScrollController.html) properties respectively. Set listeners on these controllers using the `addListener` method to receive notifications when scrolling occurs. -Listen to the vertical and horizontal scroll changes by using the [verticalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/verticalScrollController.html) and the [horizontalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/horizontalScrollController.html) properties respectively. Set the listener in the `verticalScrollController` and the `horizontalScrollController` using the `addListener` method. By subscribing to this listener, the subscribed method in the sample level will be called on vertical or horizontal scrolling. +> **NOTE:** The `intl` package is required for number formatting. Add `intl: ^0.19.0` to your `pubspec.yaml` dependencies. -The following example demonstrates how to load more rows when vertical scrolling reaches 70% of the vertical maxScrollExtent, +The following example demonstrates how to load more rows when vertical scrolling reaches 70% of the maximum scroll extent: {% tabs %} {% highlight Dart %} +import 'dart:math'; import 'package:intl/intl.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; late EmployeeDataSource _employeeDataSource; - late ScrollController verticalScrollController; + late ScrollController _verticalScrollController; void verticalListener() { if (_verticalScrollController.position.pixels >= @@ -720,6 +726,16 @@ class _EmployeeDataSource extends DataGridSource { ]); } + final List names = [ + 'Maria Anders', 'Francisco Chang', 'Roland Mendel', 'Yvonne Moncada', + 'Dominique Perrier', 'Fran Wilson', 'Giovanni Rovelli', 'Catherine Dewey' + ]; + + final List cities = [ + 'New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', + 'Philadelphia', 'San Antonio', 'San Diego', 'Dallas', 'San Jose' + ]; + void loadEmployees(int count) { final Random random = Random(); final int startIndex = employees.isNotEmpty ? employees.length : 0, @@ -748,14 +764,15 @@ class _EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-data-lazily-when-scrolling-reaches-70-in-flutter-datatable-sfdatagrid). +> **NOTE:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-data-lazily-when-scrolling-reaches-70-in-flutter-datatable-sfdatagrid). ## Increase row cache limit -By default, rows are generated based on the viewport size, and these rows are reused while scrolling. Set the [SfDataGrid.rowsCacheExtent](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsCacheExtent.html) property to avoid the visible changes caused by re-using. For example, if you show the checkbox in a column without setting the rows using this property, checkbox state changes with animation can be seen when vertical scrolling is performed. +By default, rows are generated based on the viewport size, and these rows are reused while scrolling. Set the [SfDataGrid.rowsCacheExtent](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsCacheExtent.html) property to avoid visual artifacts caused by row reuse. For example, if you display a checkbox in a column, without setting this property, you may see checkbox state animation changes during vertical scrolling. -The `rowsCacheExtent` property will create the additional rows internally with the existing visible rows, which are already allocated based on viewport size. So, the number of rows that will be reused will increase. +The `rowsCacheExtent` property creates additional rows internally alongside the visible rows allocated based on viewport size, increasing the number of rows available for reuse. + +> **NOTE:** Increasing `rowsCacheExtent` improves visual consistency but may impact performance with large datasets. Use this property judiciously based on your application's performance requirements. {% tabs %} {% highlight Dart %} @@ -821,8 +838,7 @@ The `rowsCacheExtent` property will create the additional rows internally with t If the height or width of the DataGrid is infinity, then DataGrid sets its height or width to 300 by default. Users can set the height or width based on the number of rows or columns available in DataGrid by using the [shrinkWrapRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/shrinkWrapRows.html) or [shrinkWrapColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/shrinkWrapColumns.html) property, respectively. ->**NOTE** -Shrink wrapping is significantly more expensive than setting the height and width manually. +> **NOTE:** Shrink wrapping is significantly more expensive than setting the height and width manually. Use this property only when the number of rows and columns is small. {% tabs %} {% highlight Dart %} @@ -887,7 +903,7 @@ late EmployeeDataSource _employeeDataSource; ## Retrieve the indices of visible rows and columns -In the SfDataGrid, you can obtain the starting and ending indices of the visible rows using the [DataGridController.getVisibleRowStartIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleRowStartIndex.html) and [DataGridController.getVisibleRowEndIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleRowEndIndex.html) methods, respectively, by specifying the needed `RowRegion`. Similarly, for the visible columns, you can retrieve the starting and ending indices using the [DataGridController.getVisibleColumnStartIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleColumnStartIndex.html) and [DataGridController.getVisibleColumnEndIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleColumnEndIndex.html) methods, respectively. +In the SfDataGrid, you can obtain the starting and ending indices of the visible rows using the [DataGridController.getVisibleRowStartIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleRowStartIndex.html) and [DataGridController.getVisibleRowEndIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleRowEndIndex.html) methods, respectively, by specifying the needed [RowRegion](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowRegion.html). The possible values are `header`, `body`, and `footer`. Similarly, for the visible columns, you can retrieve the starting and ending indices using the [DataGridController.getVisibleColumnStartIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleColumnStartIndex.html) and [DataGridController.getVisibleColumnEndIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/getVisibleColumnEndIndex.html) methods, respectively. {% tabs %} {% highlight Dart %} @@ -956,22 +972,24 @@ In the SfDataGrid, you can obtain the starting and ending indices of the visible {% endtabs %} ## Set the scroll offset on initial loading -SfDataGrid allows you to set the scroll offset upon initial loading for both horizontal and vertical scroll bars. This can be achieved by assigning the offset value to the [initialScrollOffset](https://api.flutter.dev/flutter/widgets/ScrollController/initialScrollOffset.html) property of the [ScrollController](https://api.flutter.dev/flutter/widgets/ScrollController-class.html) for the needed vertical or horizontal controller. + +SfDataGrid allows you to set the scroll offset upon initial loading for both horizontal and vertical scrollbars. This is achieved by assigning the offset value to the [initialScrollOffset](https://api.flutter.dev/flutter/widgets/ScrollController/initialScrollOffset.html) property of the [ScrollController](https://api.flutter.dev/flutter/widgets/ScrollController-class.html) for the required vertical or horizontal controller. + +> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - late EmployeeDataSource _employeeDataSource; late ScrollController _verticalScrollController; late ScrollController _horizontalScrollController; + late List employees; @override void initState() { super.initState(); employees = getEmployeeData(); - employeeDataSource = EmployeeDataSource(employeeData: employees); + _employeeDataSource = EmployeeDataSource(employeeData: employees); _verticalScrollController = ScrollController( initialScrollOffset: 500, ); diff --git a/Flutter/datagrid/selection.md b/Flutter/datagrid/selection.md index 1ef0b3495..2f86f25f5 100644 --- a/Flutter/datagrid/selection.md +++ b/Flutter/datagrid/selection.md @@ -10,10 +10,12 @@ documentation: ug This section explains how to enable selection in the Datagrid; modes, properties, and callbacks involved in selection and customizations available for selection. -The Datagrid allows you to select a specific row or group of rows either programmatically or by touch interactions. To enable selection, set the [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property of the SfDataGrid to a value other than `none`. SfDataGrid has different selection modes to perform the selection operation as follows. +The Datagrid allows you to select a specific row or group of rows either programmatically or by touch interactions. To enable selection, set the [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property of the SfDataGrid to a value other than `none`. The default value is `none`. SfDataGrid has different selection modes to perform the selection operation as follows. N> The [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) property must be initialized in the [source](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/source.html). The `rows` is the collection of `DataGridRow` to populate the rows in DataGrid. +N> Import the [SelectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SelectionMode.html) enum from the `syncfusion_flutter_datagrid` package to use different selection modes in your application. + ## Selection modes @@ -160,9 +162,9 @@ It allows you to select only one row. For example, you have selected a row. Now ### Multiple row selection -The SfDataGrid allows you to select multiple rows by setting the `selectionMode` property as `multiple,` where you can select multiple rows by clicking on SfDataGrid and also using the key modifiers. +The SfDataGrid allows you to select multiple rows by setting the `selectionMode` property as `multiple`, where you can select multiple rows by clicking on SfDataGrid and also using the key modifiers. -While using `multiple`, you can select multiple rows by pressing the key modifiers Shift + Down and Shift + Up. +When using `multiple`, you can select multiple rows by pressing the key modifiers Shift + Down and Shift + Up. {% tabs %} {% highlight Dart %} @@ -220,6 +222,62 @@ While using `multiple`, you can select multiple rows by pressing the key modifie N> When the `selectionMode` is `multiple`, multiple rows can be selected or deselected by clicking the respective rows. In multiple selections, pressing the navigation keys will move the current cell alone. The rows can be selected or deselected by pressing the Space key. +### Single deselect row selection + +The `singleDeselect` mode allows selection of only one row at a time. Unlike the `single` mode, tapping a selected row again will deselect it. Selecting a different row will clear the previous selection. + +{% tabs %} +{% highlight Dart %} + + @override + Widget build(BuildContext context) { + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ))), + ], + selectionMode: SelectionMode.singleDeselect)); + } + +{% endhighlight %} +{% endtabs %} + ### Disable selection The selection can be disabled by setting the `selectionMode` property as `none`. @@ -282,7 +340,9 @@ Selection on a particular row can be disabled by handling the [onCurrentCellActi ## Getting selected rows -Get the information of the selected rows by using the [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/controller.html) property. Create an instance of the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) and set it to controller property. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) property returns the selected DataGridRow and the [selectedIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedIndex.html) property returns the index of the [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) in SfDataGrid. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) denotes the last selected row in multiple selections. +Get the information of the selected rows by using the [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/controller.html) property. Create an instance of the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) and set it to the controller property. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) property returns the selected DataGridRow and the [selectedIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedIndex.html) property returns the index of the [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) in SfDataGrid. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) denotes the last selected row in multiple selections. + +N> [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) objects are expected to be long-lived, not re-created with each build. Instantiate the controller at the class level in your State class to maintain its state across widget rebuilds. {% tabs %} {% highlight Dart %} @@ -358,13 +418,11 @@ Get the information of the selected rows by using the [controller](https://pub.d {% endhighlight %} {% endtabs %} -N> DataGridController objects are expected to be long-lived, not re-created with each build. - ## Programmatic selection -When `selectionMode` is set to a value other than `none`, the selected rows from the code by setting the `DataGridController.selectedIndex`, `DataGridController.selectedRow`, or `DataGridController.selectedRows` property based on the selection mode. +You can select rows programmatically by setting the `DataGridController.selectedIndex`, `DataGridController.selectedRow`, or `DataGridController.selectedRows` property based on the selection mode. -When the selection mode is `single`, programmatically select a row in two ways either by setting the row index to the `DataGridController.selectedIndex` property, or by setting the `DataGridRow` to be selected to the `DataGridController.selectedRow` property +When the selection mode is `single`, you can select a row programmatically in two ways: by setting the row index to the `DataGridController.selectedIndex` property, or by setting the `DataGridRow` to be selected to the `DataGridController.selectedRow` property. The following code example shows how to select a row using `selectedIndex`, @@ -1025,13 +1083,13 @@ If the current cell is in edit mode, call the - -## See also - -* [DataGrid getting started](getting-started.md) -* [GitHub sample repository](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid) -* [SfDataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) \ No newline at end of file +flutter datagrid shows column header icons when hover over the header cell \ No newline at end of file diff --git a/Flutter/datagrid/getting-started.md b/Flutter/datagrid/getting-started.md index 54cdb9d60..6845a06dd 100644 --- a/Flutter/datagrid/getting-started.md +++ b/Flutter/datagrid/getting-started.md @@ -479,13 +479,3 @@ Widget build(BuildContext context) { {% endtabs %} **Note:** `SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`. - -## Next steps - -* [Styling](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Customize the appearance of SfDataGrid -* [Sorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Enable sorting on columns -* [Filtering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Filter rows based on conditions -* [Editing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Enable cell editing functionality -* [Export](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) - Export data to various formats - -For more information, refer to the complete [SfDataGrid documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) and the [GitHub samples repository](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid). From 3674a567566bae21f8958cc351ccc259f3ebb279 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Tue, 7 Jul 2026 16:55:27 +0530 Subject: [PATCH 06/18] FLUT-1038842-[others][flutter]: stacked header fixed --- Flutter/datagrid/column-types.md | 12 +- Flutter/datagrid/columns-sizing.md | 576 ++++++++++++--------------- Flutter/datagrid/data-binding.md | 8 +- Flutter/datagrid/getting-started.md | 12 +- Flutter/datagrid/overview.md | 2 +- Flutter/datagrid/stacked-headers.md | 588 ++++++++++++++-------------- 6 files changed, 567 insertions(+), 631 deletions(-) diff --git a/Flutter/datagrid/column-types.md b/Flutter/datagrid/column-types.md index d8d526936..9262d8fb3 100644 --- a/Flutter/datagrid/column-types.md +++ b/Flutter/datagrid/column-types.md @@ -11,7 +11,7 @@ documentation: ug [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for loading any type of widget in each column. The `SfDataGrid` supports two main column types: `GridColumn` for standard data binding and a `Checkbox` column for row selection. This document covers the features and customization options available for each column type. -**Note:** Ensure that you have added the `syncfusion_flutter_datagrid` package to your `pubspec.yaml` file. For more information, refer to the [getting started with Flutter DataGrid](getting-started.md) documentation. +> **Note:** Ensure that you have added the `syncfusion_flutter_datagrid` package to your `pubspec.yaml` file. For more information, refer to the [getting started with Flutter DataGrid](getting-started.md) documentation. ## GridColumn @@ -86,7 +86,7 @@ The column can be bound to a property in a data object using the [GridColumn.col [GridColumn.visible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/visible.html) property can be used to set a column as hidden. The default value of the `visible` property is true. -**Note:** Set the `visible` property to `false` instead of setting column width as `0` to hide a column. +> **Note:** Set the `visible` property to `false` instead of setting column width as `0` to hide a column. {% tabs %} {% highlight Dart %} @@ -154,7 +154,7 @@ The column can be bound to a property in a data object using the [GridColumn.col [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows you to customize the width of each [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) in the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) collection. To customize column width, use the [GridColumn.width](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/width.html) property. Specify the width value in logical pixels. By default, this property will not be assigned any value, and the column renders based on the [SfDataGrid.defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/defaultColumnWidth.html) property. -**Note:** Set the `visible` property to `false` instead of setting column width as `0` to hide a column. +> **Note:** Set the `visible` property to `false` instead of setting column width as `0` to hide a column. {% tabs %} {% highlight Dart %} @@ -222,7 +222,7 @@ The column can be bound to a property in a data object using the [GridColumn.col By setting the [showCheckboxColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showCheckboxColumn.html) property to `true`, you can select or deselect individual rows using checkboxes in each row. The checkbox column will be added as the first column in the grid. -**Note:** Row selection is applied only if you set the [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property to a value other than `none`. The checkbox state automatically synchronizes with the row selection state. +> **Note:** Row selection is applied only if you set the [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property to a value other than `none`. The checkbox state automatically synchronizes with the row selection state. {% tabs %} {% highlight Dart %} @@ -508,7 +508,7 @@ The background color of the entire checkbox column can be customized by using th Get the checked items by using the [DataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) property. The checkbox state and row selection state are synchronized, so you can retrieve checked rows through the controller's selection properties. -**Note:** Ensure the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) is assigned to the `SfDataGrid.controller` property for programmatic access to selection information. +> **Note:** Ensure the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) is assigned to the `SfDataGrid.controller` property for programmatic access to selection information. {% tabs %} {% highlight Dart %} @@ -734,7 +734,7 @@ The following are the limitations of the checkbox column: To display column header icons, such as sort and filter icons, when the mouse hovers over a column header, set the [SfDataGrid.showColumnHeaderIconOnHover](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showColumnHeaderIconOnHover.html) property to `true`. This feature is available only on web and desktop platforms. -**Note:** This feature requires the [SfDataGrid.allowSorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowSorting.html) or [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) properties to be enabled for the icons to appear. +> **Note:** This feature requires the [SfDataGrid.allowSorting](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowSorting.html) or [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) properties to be enabled for the icons to appear. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/columns-sizing.md b/Flutter/datagrid/columns-sizing.md index 556f8040c..a34b31cb5 100644 --- a/Flutter/datagrid/columns-sizing.md +++ b/Flutter/datagrid/columns-sizing.md @@ -9,9 +9,6 @@ documentation: ug # Column sizing in Flutter DataGrid (SfDataGrid) -> **NOTE** - Ensure that SfDataGrid is installed and configured in your Flutter project. Refer to the [getting started guide](getting-started.md) for setup instructions. - [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows setting the column widths based on certain logic using the [SfDataGrid.columnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthMode.html) or [GridColumn.columnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnWidthMode.html) property. The following is the list of predefined column sizing options available. | Mode | Description | @@ -23,23 +20,24 @@ documentation: ug | ColumnWidthMode.fill | Divides the total width equally for columns. | | ColumnWidthMode.none | No sizing. Default column width (80.0) or explicitly defined width is set to the column. | -> **NOTE** - [ColumnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthMode.html) will not work when the column width is defined explicitly. `columnWidthMode` calculates column width based on `minimumWidth` and `maximumWidth` properties. For optimal performance with large datasets, consider using `ColumnWidthMode.none` or `ColumnWidthMode.fill` instead of `ColumnWidthMode.auto`. +> **Note:** [ColumnWidthMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthMode.html) will not work when the column width is defined explicitly. `columnWidthMode` calculates column width based on `minimumWidth` and `maximumWidth` properties. For optimal performance with large datasets, consider using `ColumnWidthMode.none` or `ColumnWidthMode.fill` instead of `ColumnWidthMode.auto`. The following example shows how to set the width equally for columns based on the viewport size. {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override @@ -100,73 +98,73 @@ import 'package:flutter/material.dart'; {% endhighlight %} {% endtabs %} -> **NOTE** -The `GridColumn.columnWidthMode` takes higher priority than the `SfDataGrid.columnWidthMode`. +> **Note:** The `GridColumn.columnWidthMode` takes higher priority than the `SfDataGrid.columnWidthMode`. ![columns filled based on view port size in flutter datagrid](images/autofit-columns/flutter-datagrid-fill-columns.png) ## Consider all the rows to calculate the autofit size -By default, the autofit calculation is performed for only visible rows. You can use the [SfDataGrid.columnWidthCalculationRange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthCalculationRange.html) property as [ColumnWidthCalculationRange.allRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthCalculationRange.html) to perform the autofit calculation for all the available rows. +By default, the autofit calculation is performed for only visible rows. You can use the [SfDataGrid.columnWidthCalculationRange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columnWidthCalculationRange.html) property as [ColumnWidthCalculationRange.allRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/ColumnWidthCalculationRange.html#allRows) to perform the autofit calculation for all the available rows. {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + body: SfDataGrid( source: _employeeDataSource, columnWidthMode: ColumnWidthMode.auto, columnWidthCalculationRange: ColumnWidthCalculationRange.allRows, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - softWrap: false, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerRight, + child: Text('ID', softWrap: false), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - softWrap: false, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerLeft, + child: Text('Name', softWrap: false), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - softWrap: false, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', softWrap: false), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - softWrap: false, - ))) - ]); + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerRight, + child: Text('Salary', softWrap: false), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -176,81 +174,72 @@ import 'package:flutter/material.dart'; By default, `EdgeInsets.all(16.0)` is added with the auto width or height value. You can change the padding for specific columns by using the [GridColumn.autoFitPadding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/autoFitPadding.html) property. You can also use asymmetric padding values (e.g., `EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0)`) for fine-grained control. ->**NOTE** -`GridColumn.autoFitPadding` is applicable for header cells as well. +> **Note:** `GridColumn.autoFitPadding` is applicable for header cells as well. {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employees: _employees); } @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + body: SfDataGrid( source: _employeeDataSource, columnWidthMode: ColumnWidthMode.auto, columns: [ GridColumn( - columnName: 'id', - autoFitPadding: EdgeInsets.all(10.0), - label: Container( - padding: EdgeInsets.all(10.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - softWrap: false, - ))), + columnName: 'id', + autoFitPadding: EdgeInsets.all(10.0), + label: Container( + padding: EdgeInsets.all(10.0), + alignment: Alignment.centerRight, + child: Text('ID', softWrap: false), + ), + ), GridColumn( - columnName: 'name', - autoFitPadding: EdgeInsets.all(10.0), - label: Container( - padding: EdgeInsets.all(10.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - softWrap: false, - ))), + columnName: 'name', + autoFitPadding: EdgeInsets.all(10.0), + label: Container( + padding: EdgeInsets.all(10.0), + alignment: Alignment.centerLeft, + child: Text('Name', softWrap: false), + ), + ), GridColumn( - columnName: 'designation', - autoFitPadding: EdgeInsets.all(10.0), - label: Container( - padding: EdgeInsets.all(10.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - softWrap: false, - ))), + columnName: 'designation', + autoFitPadding: EdgeInsets.all(10.0), + label: Container( + padding: EdgeInsets.all(10.0), + alignment: Alignment.centerLeft, + child: Text('Designation', softWrap: false), + ), + ), GridColumn( - columnName: 'salary', - autoFitPadding: EdgeInsets.all(10.0), - label: Container( - padding: EdgeInsets.all(10.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - softWrap: false, - ))) - ]); + columnName: 'salary', + autoFitPadding: EdgeInsets.all(10.0), + label: Container( + padding: EdgeInsets.all(10.0), + alignment: Alignment.centerRight, + child: Text('Salary', softWrap: false), + ), + ), + ], + ), + ); } -class Employee { - final int id; - final String name; - final String designation; - final int salary; - - Employee({required this.id, required this.name, required this.designation, required this.salary}); -} - class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { _employeeData = employees @@ -283,15 +272,6 @@ class EmployeeDataSource extends DataGridSource { } } -List getEmployeeData() { - return [ - Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), - Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), - ]; -} - {% endhighlight %} {% endtabs %} @@ -304,76 +284,82 @@ By default, the cell width is calculated based on the default text style. To cal {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); + List _employees = []; late EmployeeDataSource _employeeDataSource; + final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employees: _employees); } @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + body: SfDataGrid( source: _employeeDataSource, columnSizer: _customColumnSizer, columnWidthMode: ColumnWidthMode.auto, columns: [ GridColumn( - columnName: 'id', - autoFitPadding: EdgeInsets.all(12.0), - label: Container( - padding: EdgeInsets.all(12.0), - alignment: Alignment.center, - child: Text( - 'ID', - ))), + columnName: 'id', + autoFitPadding: EdgeInsets.all(12.0), + label: Container( + padding: EdgeInsets.all(12.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), GridColumn( - columnName: 'name', - autoFitPadding: EdgeInsets.all(12.0), - label: Container( - padding: EdgeInsets.all(12.0), - alignment: Alignment.center, - child: Text( - 'Name', - style: TextStyle( - fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), - ))), + columnName: 'name', + autoFitPadding: EdgeInsets.all(12.0), + label: Container( + padding: EdgeInsets.all(12.0), + alignment: Alignment.center, + child: Text( + 'Name', + style: TextStyle( + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + ), + ), + ), + ), GridColumn( - columnName: 'designation', - autoFitPadding: EdgeInsets.all(12.0), - label: Container( - padding: EdgeInsets.all(12.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - style: TextStyle( - fontWeight: FontWeight.bold, fontStyle: FontStyle.italic), - ))), + columnName: 'designation', + autoFitPadding: EdgeInsets.all(12.0), + label: Container( + padding: EdgeInsets.all(12.0), + alignment: Alignment.center, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontWeight: FontWeight.bold, + fontStyle: FontStyle.italic, + ), + ), + ), + ), GridColumn( - columnName: 'salary', - autoFitPadding: EdgeInsets.all(12.0), - label: Container( - padding: EdgeInsets.all(12.0), - alignment: Alignment.center, - child: Text('Salary'))), - ]); + columnName: 'salary', + autoFitPadding: EdgeInsets.all(12.0), + label: Container( + padding: EdgeInsets.all(12.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); } -class Employee { - final int id; - final String name; - final String designation; - final int salary; - - Employee({required this.id, required this.name, required this.designation, required this.salary}); -} - class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { _employeeData = employees @@ -429,15 +415,6 @@ class CustomColumnSizer extends ColumnSizer { } } -List getEmployeeData() { - return [ - Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), - Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), - ]; -} - {% endhighlight %} {% endtabs %} @@ -450,72 +427,73 @@ The cell width is calculated by default based on the `DataGridCell.value` proper {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:intl/intl.dart'; - final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); + List _employees = []; late EmployeeDataSource _employeeDataSource; + final CustomColumnSizer _customColumnSizer = CustomColumnSizer(); @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getFormattedEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employees: _employees); } @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + body: SfDataGrid( source: _employeeDataSource, columnSizer: _customColumnSizer, columnWidthMode: ColumnWidthMode.fitByCellValue, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - softWrap: false, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerRight, + child: Text('ID', softWrap: false), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - softWrap: false, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerLeft, + child: Text('Name', softWrap: false), + ), + ), GridColumn( - columnName: 'dob', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerLeft, - child: Text( - 'DOB', - softWrap: false, - ))), + columnName: 'dob', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerLeft, + child: Text('DOB', softWrap: false), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - softWrap: false, - ))) - ]); + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.centerRight, + child: Text('Salary', softWrap: false), + ), + ), + ], + ), + ); } class Employee { + Employee(this.id, this.name, this.dob, this.salary); + final int id; final String name; final DateTime dob; final int salary; - - Employee({required this.id, required this.name, required this.dob, required this.salary}); } class EmployeeDataSource extends DataGridSource { @@ -573,15 +551,6 @@ class CustomColumnSizer extends ColumnSizer { } } -List getFormattedEmployeeData() { - return [ - Employee(id: 10001, name: 'James', dob: DateTime(1990, 5, 15), salary: 60000), - Employee(id: 10002, name: 'Kathryn', dob: DateTime(1992, 8, 22), salary: 30000), - Employee(id: 10003, name: 'Lara', dob: DateTime(1995, 3, 10), salary: 15000), - Employee(id: 10004, name: 'Michael', dob: DateTime(1993, 12, 5), salary: 15000), - ]; -} - {% endhighlight %} {% endtabs %} @@ -594,61 +563,61 @@ While setting `SfDataGrid.columnWidthMode` as `lastColumnFill`, the remaining wi {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columnWidthMode: ColumnWidthMode.lastColumnFill, - columns: [ + body: SfDataGrid( + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.lastColumnFill, + columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))) - ])); + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -661,61 +630,61 @@ The following example shows Name column is set as `lastColumnFill` mode. {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columns: [ + body: SfDataGrid( + source: _employeeDataSource, + columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - columnWidthMode: ColumnWidthMode.lastColumnFill, - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + columnWidthMode: ColumnWidthMode.lastColumnFill, + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))) - ])); + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -727,24 +696,11 @@ import 'package:flutter/material.dart'; By default, column widths are calculated based on the `columnWidthMode` property on the initial loading of the DataGrid. When the data source is changed for the same DataGrid at run time, the DataGrid does not recalculate the column widths. To recalculate the column widths at run time when the data source is changed or data is updated, override the [shouldRecalculateColumnWidths](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/shouldRecalculateColumnWidths.html) method and return `true`. Then, call `notifyListeners()` to trigger the recalculation. -> **NOTE** -Returning `true` may impact performance as the column widths are recalculated whenever `notifyListeners()` is called. If you know that column widths will be the same whenever underlying data changes, return `false` from this method. +> **Note:** Returning `true` may impact performance as the column widths are recalculated whenever `notifyListeners()` is called. If you know that column widths will be the same whenever underlying data changes, return `false` from this method. {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; - -class Employee { - final int id; - final String name; - final String designation; - final int salary; - - Employee({required this.id, required this.name, required this.designation, required this.salary}); -} - class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { dataGridRows = employees @@ -801,15 +757,5 @@ class EmployeeDataSource extends DataGridSource { notifyListeners(); } } - -List getEmployeeData() { - return [ - Employee(id: 10001, name: 'James', designation: 'Project Manager', salary: 60000), - Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), - ]; -} - {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/data-binding.md b/Flutter/datagrid/data-binding.md index 4cf3e614e..9d84da691 100644 --- a/Flutter/datagrid/data-binding.md +++ b/Flutter/datagrid/data-binding.md @@ -19,7 +19,7 @@ The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/lates `DataGridSource` objects are expected to be long-lived, not recreated with each build. -**Note:** Ensure the `columnName` property in `DataGridCell` matches the `columnName` in the corresponding `GridColumn` definitions. This alignment is essential for the DataGrid to correctly display and manage the data. +> **Note:** Ensure the `columnName` property in `DataGridCell` matches the `columnName` in the corresponding `GridColumn` definitions. This alignment is essential for the DataGrid to correctly display and manage the data. The following example shows how to create the `DataGridSource`, @@ -151,13 +151,13 @@ Widget build(BuildContext context) { {% endhighlight %} {% endtabs %} -**Note:** `ColumnWidthMode.lastColumnFill` automatically adjusts the width of the last column to fill any remaining space in the DataGrid. +> **Note:** `ColumnWidthMode.lastColumnFill` automatically adjusts the width of the last column to fill any remaining space in the DataGrid. ## Data manipulation in Flutter DataGrid (SfDataGrid) `SfDataGrid` provides support to update or refresh the DataGrid when underlying data is updated via CRUD operations. -**Note:** +> **Note:** - `notifyListeners` must be called from inside the `DataGridSource`. Since it is a protected method, wrap it in a public method like `updateDataGridSource` that can be called from the widget level. - Requires `syncfusion_flutter_datagrid` package version 20.0.0 or later. @@ -418,4 +418,4 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -**Note:** Use `notifyDataSourceListeners` with a specific `RowColumnIndex` for better performance when updating individual cells. Use `notifyListeners` only when the entire row or multiple cells need to be refreshed. +> **Note:** Use `notifyDataSourceListeners` with a specific `RowColumnIndex` for better performance when updating individual cells. Use `notifyListeners` only when the entire row or multiple cells need to be refreshed. diff --git a/Flutter/datagrid/getting-started.md b/Flutter/datagrid/getting-started.md index 6845a06dd..14fe41c50 100644 --- a/Flutter/datagrid/getting-started.md +++ b/Flutter/datagrid/getting-started.md @@ -11,7 +11,7 @@ documentation: ug This section explains the steps required to add the SfDataGrid widget and its features. This section covers only the basic features needed to get started with the Syncfusion® Flutter DataGrid widget. -**Note:** Ensure you have Flutter SDK installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. +> **Note:** Ensure you have Flutter SDK installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. To get started quickly with Flutter SfDataGrid, check out this video: @@ -33,7 +33,7 @@ Add the Syncfusion® Flutter DataGrid dependency to your `pubspec.yaml` file. {% endhighlight %} -**Note:** Here **xx.x.xx** denotes the current version of the [`Syncfusion® Flutter DataGrid`](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) package. Refer to the [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) page to check the latest available version. +> **Note:** Here **xx.x.xx** denotes the current version of the [`Syncfusion® Flutter DataGrid`](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) package. Refer to the [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid/versions) page to check the latest available version. **Get packages** @@ -185,7 +185,7 @@ List getEmployeeData() { * **`buildRow`** - Returns a [DataGridRowAdapter](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRowAdapter-class.html) that builds the widget for each cell in the row. -**Note:** `DataGridSource` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridSource` once in the `initState()` method and reuse it. +> **Note:** `DataGridSource` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridSource` once in the `initState()` method and reuse it. {% tabs %} {% highlight Dart %} @@ -254,7 +254,7 @@ Widget build(BuildContext context) { {% endhighlight %} {% endtabs %} -**Note:** You can download the demo application from [GitHub](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid). +> **Note:** You can download the demo application from [GitHub](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid). ## Defining columns @@ -389,7 +389,7 @@ You can retrieve information about the selected rows using the [DataGridControll * [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) - Gets the currently selected row * [selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) - Gets all selected rows -**Note:** `DataGridController` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridController` once in your State class and reuse it. +> **Note:** `DataGridController` objects are expected to be long-lived, not recreated with each build. Initialize the `DataGridController` once in your State class and reuse it. {% tabs %} {% highlight Dart %} @@ -478,4 +478,4 @@ Widget build(BuildContext context) { {% endhighlight %} {% endtabs %} -**Note:** `SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`. +> **Note:** `SfDataGrid` supports selection via keyboard interaction for the Web and Desktop platform when `selectionMode` is not `none`. diff --git a/Flutter/datagrid/overview.md b/Flutter/datagrid/overview.md index 09da3b9c2..5c0fe83bc 100644 --- a/Flutter/datagrid/overview.md +++ b/Flutter/datagrid/overview.md @@ -11,7 +11,7 @@ documentation: ug The Syncfusion® Flutter DataGrid is used to display and manipulate data in a tabular view. It is built from the ground up to achieve the best possible performance, even when loading large amounts of data. -**Note:** The SfDataGrid widget is compatible with iOS, Android, Web, macOS, and Windows platforms. Ensure you have Flutter SDK 3.0 or later installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. +> **Note:** The SfDataGrid widget is compatible with iOS, Android, Web, macOS, and Windows platforms. Ensure you have Flutter SDK 3.0 or later installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. ![Overview Flutter Datagrid](images/overview/flutter-datagrid-overview.png) diff --git a/Flutter/datagrid/stacked-headers.md b/Flutter/datagrid/stacked-headers.md index e689d0964..ae13b388a 100644 --- a/Flutter/datagrid/stacked-headers.md +++ b/Flutter/datagrid/stacked-headers.md @@ -18,89 +18,81 @@ Each [StackedHeaderRow](https://pub.dev/documentation/syncfusion_flutter_datagri {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - gridLinesVisibility: GridLinesVisibility.both, - headerGridLinesVisibility: GridLinesVisibility.both, - source: _productDataSource, - columns: [ - GridColumn( - columnName: 'orderId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'customerName', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'productId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'product', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Product', - overflow: TextOverflow.ellipsis, - ) - ) - ), - ], - stackedHeaderRows: [ - StackedHeaderRow(cells: [ - StackedHeaderCell( - columnNames: ['orderId', 'customerName'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Customer Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) + return Scaffold( + body: SfDataGrid( + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + source: _productDataSource, + columns: [ + GridColumn( + columnName: 'orderId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'customerName', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'productId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'product', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Product', overflow: TextOverflow.ellipsis), + ), + ), + ], + stackedHeaderRows: [ + StackedHeaderRow( + cells: [ + StackedHeaderCell( + columnNames: ['orderId', 'customerName'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Customer Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + StackedHeaderCell( + columnNames: ['productId', 'product'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Product Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ], ), - StackedHeaderCell( - columnNames: ['productId', 'product'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Product Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) - ) - ]) - ] + ], + ), ); } @@ -109,7 +101,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ![flutter datagrid shows stacked headers](images/stacked-headers/flutter-stacked-headers.png) -> **Important:** The `columnNames` property must contain valid column names that exactly match the `columnName` properties defined in your grid columns. Column names are case-sensitive, and specifying non-existent column names will result in those columns not being grouped under the stacked header. +> **Note:** The `columnNames` property must contain valid column names that exactly match the `columnName` properties defined in your grid columns. Column names are case-sensitive, and specifying non-existent column names will result in those columns not being grouped under the stacked header. ## Multi stacked headers @@ -123,98 +115,97 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - gridLinesVisibility: GridLinesVisibility.both, - headerGridLinesVisibility: GridLinesVisibility.both, - source: _productDataSource, - columns: [ - GridColumn( - columnName: 'orderId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'customerName', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'productId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'product', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Product', - overflow: TextOverflow.ellipsis, - ) - ) - ), - ], - stackedHeaderRows: [ - StackedHeaderRow(cells: [ - StackedHeaderCell( - columnNames: ['orderId', 'customerName', 'productId', 'product'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Order Shipment Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) + return Scaffold( + body: SfDataGrid( + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + source: _productDataSource, + columns: [ + GridColumn( + columnName: 'orderId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'customerName', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'productId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'product', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Product', overflow: TextOverflow.ellipsis), + ), + ), + ], + stackedHeaderRows: [ + StackedHeaderRow( + cells: [ + StackedHeaderCell( + columnNames: [ + 'orderId', + 'customerName', + 'productId', + 'product', + ], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Order Shipment Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ], ), - ]), - StackedHeaderRow(cells: [ - StackedHeaderCell( - columnNames: ['orderId', 'customerName'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Customer Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) + StackedHeaderRow( + cells: [ + StackedHeaderCell( + columnNames: ['orderId', 'customerName'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Customer Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + StackedHeaderCell( + columnNames: ['productId', 'product'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Product Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ], ), - StackedHeaderCell( - columnNames: ['productId', 'product'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Product Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) - ) - ]) - ] + ], + ), ); } @@ -238,12 +229,13 @@ Use the `onQueryRowHeight` callback to apply custom heights to specific stacked {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( + return Scaffold( + body: SfDataGrid( gridLinesVisibility: GridLinesVisibility.both, headerGridLinesVisibility: GridLinesVisibility.both, source: _productDataSource, @@ -255,64 +247,70 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; }, columns: [ GridColumn( - columnName: 'orderId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'orderId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'customerName', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'customerName', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'productId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'productId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'product', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Product', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'product', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Product', overflow: TextOverflow.ellipsis), + ), + ), ], stackedHeaderRows: [ - StackedHeaderRow(cells: [ - StackedHeaderCell( + StackedHeaderRow( + cells: [ + StackedHeaderCell( columnNames: ['orderId', 'customerName'], child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Customer Details', - overflow: TextOverflow.ellipsis, - )))), - StackedHeaderCell( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Customer Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + StackedHeaderCell( columnNames: ['productId', 'product'], child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Product Details', - overflow: TextOverflow.ellipsis, - )))) - ]) - ]); + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Product Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ], + ), + ], + ), + ); } {% endhighlight %} @@ -327,90 +325,82 @@ You can set a uniform height for all stacked header rows and the column header r {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - gridLinesVisibility: GridLinesVisibility.both, - headerGridLinesVisibility: GridLinesVisibility.both, - headerRowHeight: 60.0, - source: _productDataSource, - columns: [ - GridColumn( - columnName: 'orderId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'customerName', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'productId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) - ), - GridColumn( - columnName: 'product', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Product', - overflow: TextOverflow.ellipsis, - ) - ) - ), - ], - stackedHeaderRows: [ - StackedHeaderRow(cells: [ - StackedHeaderCell( - columnNames: ['orderId', 'customerName'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Customer Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) + return Scaffold( + body: SfDataGrid( + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + headerRowHeight: 60.0, + source: _productDataSource, + columns: [ + GridColumn( + columnName: 'orderId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'customerName', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'productId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'product', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Product', overflow: TextOverflow.ellipsis), + ), ), - StackedHeaderCell( - columnNames: ['productId', 'product'], - child: Container( - color: const Color(0xFFF1F1F1), - child: Center( - child: Text( - 'Product Details', - overflow: TextOverflow.ellipsis, - ) - ) - ) - ) - ]) - ] + ], + stackedHeaderRows: [ + StackedHeaderRow( + cells: [ + StackedHeaderCell( + columnNames: ['orderId', 'customerName'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Customer Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + StackedHeaderCell( + columnNames: ['productId', 'product'], + child: Container( + color: const Color(0xFFF1F1F1), + child: Center( + child: Text( + 'Product Details', + overflow: TextOverflow.ellipsis, + ), + ), + ), + ), + ], + ), + ], + ), ); } From c0980726e0c7f9b635fa9640e332ed4994ce8f95 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Tue, 7 Jul 2026 17:30:48 +0530 Subject: [PATCH 07/18] FLUT-1038842-[others][flutter]: sorting fixed --- Flutter/datagrid/sorting.md | 762 +++++++++++++++++++----------------- 1 file changed, 398 insertions(+), 364 deletions(-) diff --git a/Flutter/datagrid/sorting.md b/Flutter/datagrid/sorting.md index 6a7b1de59..6ee4a50e2 100644 --- a/Flutter/datagrid/sorting.md +++ b/Flutter/datagrid/sorting.md @@ -13,11 +13,9 @@ The SfDataGrid provides built-in support to sort one or more columns by setting By default, the SfDataGrid shows an unsorted icon on every column header to indicate that sorting is enabled in the column. When sorting is applied, the SfDataGrid shows a sort icon in the column header to indicate the sort direction. -> **Note:** This feature requires `syncfusion_flutter_datagrid` package. Ensure the package is added to your `pubspec.yaml` file. - ## Programmatic sorting -The SfDataGrid provides support to sort columns programmatically by creating [SortColumnDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SortColumnDetails-class.html) objects and adding them to the [SfDataGrid.source.sortedColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/sortedColumns.html) collection. After adding the sort details, call the [SfDataGrid.source.sort()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/sort.html) method to apply the sort. +The SfDataGrid provides support to sort columns programmatically by creating [SortColumnDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SortColumnDetails-class.html) objects and adding them to the [DataGridSource.sortedColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/sortedColumns.html) collection. After adding the sort details, call the [DataGridSource.sort()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/sort.html) method to apply the sort. The `SortColumnDetails` object holds the following properties: @@ -115,51 +113,47 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - allowMultiColumnSorting: true, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + allowMultiColumnSorting: true, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } - {% endhighlight %} {% endtabs %} @@ -177,52 +171,50 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - allowMultiColumnSorting: true, - allowTriStateSorting: true, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + allowMultiColumnSorting: true, + allowTriStateSorting: true, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } + {% endhighlight %} {% endtabs %} @@ -240,49 +232,46 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - sortingGestureType: SortingGestureType.doubleTap, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + sortingGestureType: SortingGestureType.doubleTap, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -330,10 +319,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ), + child: Text('ID', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -341,10 +327,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ), + child: Text('Name', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -352,10 +335,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ), + child: Text('City', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -363,10 +343,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ), + child: Text('Freight', overflow: TextOverflow.ellipsis), ), ), ], @@ -374,6 +351,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ); } + {% endhighlight %} {% endtabs %} @@ -389,50 +367,47 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - allowMultiColumnSorting: true, - showSortNumbers: true, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + allowMultiColumnSorting: true, + showSortNumbers: true, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -458,41 +433,50 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), body: SfDataGridTheme( data: SfDataGridThemeData( - sortOrderNumberBackgroundColor: Colors.tealAccent, - sortOrderNumberColor: Colors.pink), + sortOrderNumberBackgroundColor: Colors.tealAccent, + sortOrderNumberColor: Colors.pink, + ), child: SfDataGrid( - source: employeeDataSource, - columnWidthMode: ColumnWidthMode.auto, - allowSorting: true, - allowMultiColumnSorting: true, - showSortNumbers: true, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.center, - child: const Text( - 'ID'))), - GridColumn( - columnName: 'name', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.center, - child: const Text('Name'))), - GridColumn( - columnName: 'city', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.center, - child: const Text('City'))), - GridColumn( - columnName: 'freight', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.center, - child: const Text('Freight'))), - ]), + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.auto, + allowSorting: true, + allowMultiColumnSorting: true, + showSortNumbers: true, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.center, + child: const Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.center, + child: const Text('Name'), + ), + ), + GridColumn( + columnName: 'city', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.center, + child: const Text('City'), + ), + ), + GridColumn( + columnName: 'freight', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.center, + child: const Text('Freight'), + ), + ), + ], + ), ), ); } @@ -514,49 +498,46 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', allowSorting: false, label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } {% endhighlight %} @@ -575,52 +556,49 @@ import 'package:syncfusion_flutter_core/theme.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGridTheme( - data: SfDataGridThemeData(sortIconColor: Colors.redAccent), - child: SfDataGrid( - source: _employeeDataSource, - allowSorting: true, - allowMultiColumnSorting: true, - columns: [ - GridColumn( + body: SfDataGridTheme( + data: SfDataGridThemeData(sortIconColor: Colors.redAccent), + child: SfDataGrid( + source: _employeeDataSource, + allowSorting: true, + allowMultiColumnSorting: true, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'city', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'freight', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Freight', - overflow: TextOverflow.ellipsis, - ))), - ], + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Freight', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), ), - )); + ); } {% endhighlight %} @@ -640,7 +618,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( + body: SfDataGrid( source: _employeeDataSource, allowSorting: true, allowMultiColumnSorting: true, @@ -648,40 +626,38 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; headerGridLinesVisibility: GridLinesVisibility.both, columns: [ GridColumn( - sortIconPosition: ColumnHeaderIconPosition.start, - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + sortIconPosition: ColumnHeaderIconPosition.start, + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.centerRight, - child: Text('Salary' - ))), + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.centerRight, + child: Text('Salary'), + ), + ), ], ), ); @@ -715,8 +691,8 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; Widget? icon; String columnName = ''; context.visitAncestorElements((element) { - if (element.widget is GridHeaderCell) { - final headerCell = element.widget as GridHeaderCell; + if (element.widget is GridHeaderCellElement) { + final headerCell = element.widget as GridHeaderCellElement; columnName = headerCell.column.columnName; } return true; @@ -725,9 +701,11 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; .where((element) => element.name == columnName) .firstOrNull; if (sortedColumn != null) { - if (sortedColumn.sortDirection == DataGridSortDirection.ascending) { + if (sortedColumn.sortDirection == + DataGridSortDirection.ascending) { icon = const Icon(Icons.arrow_circle_up_rounded, size: 16); - } else if (sortedColumn.sortDirection == DataGridSortDirection.descending) { + } else if (sortedColumn.sortDirection == + DataGridSortDirection.descending) { icon = const Icon(Icons.arrow_circle_down_rounded, size: 16); } } @@ -740,31 +718,37 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; allowSorting: true, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerRight, - child: const Text( - 'ID', - ))), + columnName: 'id', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerRight, + child: const Text('ID'), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerLeft, - child: const Text('Name'))), + columnName: 'name', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerLeft, + child: const Text('Name'), + ), + ), GridColumn( - columnName: 'city', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerLeft, - child: const Text('City'))), + columnName: 'city', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerLeft, + child: const Text('City'), + ), + ), GridColumn( - columnName: 'freight', - label: Container( - padding: const EdgeInsets.symmetric(horizontal: 8.0), - alignment: Alignment.centerRight, - child: const Text('Freight'))), + columnName: 'freight', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 8.0), + alignment: Alignment.centerRight, + child: const Text('Freight'), + ), + ), ], ), ), @@ -790,18 +774,29 @@ Sort columns by string length instead of alphabetical order by overriding the `c {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; +import 'package:collection/collection.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { dataGridRows = employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), - DataGridCell(columnName: 'salary', value: dataGridRow.salary) - ])) + columnName: 'designation', + value: dataGridRow.designation, + ), + DataGridCell( + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -813,9 +808,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -823,27 +819,37 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } @override int compare(DataGridRow? a, DataGridRow? b, SortColumnDetails sortColumn) { - final String? value1 = a - ?.getCells() - .firstWhereOrNull((element) => element.columnName == sortColumn.name) - ?.value as String?; - final String? value2 = b - ?.getCells() - .firstWhereOrNull((element) => element.columnName == sortColumn.name) - ?.value as String?; + final String? value1 = + a + ?.getCells() + .firstWhereOrNull( + (element) => element.columnName == sortColumn.name, + ) + ?.value + as String?; + final String? value2 = + b + ?.getCells() + .firstWhereOrNull( + (element) => element.columnName == sortColumn.name, + ) + ?.value + as String?; if (value1 == null || value2 == null) { return 0; } final int lengthComparison = value1.length.compareTo(value2.length); - + if (sortColumn.sortDirection == DataGridSortDirection.ascending) { return lengthComparison; } else { @@ -866,18 +872,29 @@ Sort string columns in a case-insensitive manner by overriding the `compare` met {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; +import 'package:collection/collection.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employees}) { dataGridRows = employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), - DataGridCell(columnName: 'salary', value: dataGridRow.salary) - ])) + columnName: 'designation', + value: dataGridRow.designation, + ), + DataGridCell( + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -889,9 +906,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -899,28 +917,40 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } @override int compare(DataGridRow? a, DataGridRow? b, SortColumnDetails sortColumn) { if (sortColumn.name == 'name') { - final String? value1 = a - ?.getCells() - .firstWhereOrNull((element) => element.columnName == sortColumn.name) - ?.value as String?; - final String? value2 = b - ?.getCells() - .firstWhereOrNull((element) => element.columnName == sortColumn.name) - ?.value as String?; + final String? value1 = + a + ?.getCells() + .firstWhereOrNull( + (element) => element.columnName == sortColumn.name, + ) + ?.value + as String?; + final String? value2 = + b + ?.getCells() + .firstWhereOrNull( + (element) => element.columnName == sortColumn.name, + ) + ?.value + as String?; if (value1 == null || value2 == null) { return 0; } - final int comparisonResult = value1.toLowerCase().compareTo(value2.toLowerCase()); - + final int comparisonResult = value1.toLowerCase().compareTo( + value2.toLowerCase(), + ); + if (sortColumn.sortDirection == DataGridSortDirection.ascending) { return comparisonResult; } else { @@ -948,6 +978,9 @@ Use the [performSorting](https://pub.dev/documentation/syncfusion_flutter_datagr {% tabs %} {% highlight Dart %} +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:collection/collection.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; final StreamController loadingController = StreamController(); @@ -962,11 +995,12 @@ class Employee { class _MyHomePageState extends State { late EmployeeDataSource employeeDataSource; + List employees = []; @override void initState() { super.initState(); - final employees = getEmployeeData(); + employees = getEmployeeData(); employeeDataSource = EmployeeDataSource(employeeData: employees); } @@ -1025,7 +1059,7 @@ class _MyHomePageState extends State { @override void dispose() { - loadingController.dispose(); + loadingController.close(); super.dispose(); } } From 4fdcb001d99b8e7a5234c90a909678c38c5ce1c6 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Tue, 7 Jul 2026 18:42:42 +0530 Subject: [PATCH 08/18] FLUT-1038842-[others][flutter]: Till Editing fixed --- Flutter/datagrid/editing.md | 158 +++++++------ Flutter/datagrid/filtering.md | 294 ++++++++++------------- Flutter/datagrid/grouping.md | 427 +++++++++++++++++++--------------- 3 files changed, 453 insertions(+), 426 deletions(-) diff --git a/Flutter/datagrid/editing.md b/Flutter/datagrid/editing.md index 0bea1475f..fcaadb675 100644 --- a/Flutter/datagrid/editing.md +++ b/Flutter/datagrid/editing.md @@ -11,12 +11,6 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) supports editing the cell values by setting the [SfDataGrid.allowEditing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowEditing.html) property to true, [SfDataGrid.navigationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) to cell, and [SfDataGrid.selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) to a value other than none. ->**NOTE** - **Requirements**: Flutter 2.0 or later, `syncfusion_flutter_datagrid` package (latest version recommended). The `collection` package is required for the `firstWhereOrNull` helper method used in examples. - ->**NOTE** - The editing feature requires the `syncfusion_flutter_datagrid` package. Ensure you have added it to your `pubspec.yaml` file and imported it in your code. - By default, the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) does not load any widget when a cell enters edit mode. You must provide the required widget when a cell enters edit mode by returning it through the [DataGridSource.buildEditWidget](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildEditWidget.html) method in the [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/DataGridSource.html) class. The following arguments are passed in the `buildEditWidget` method. @@ -30,8 +24,7 @@ We recommend saving the edited value through the editor widgets in the [DataGrid The following example shows how to enable editing in Datagrid and commit the edited cell value in the `onCellSubmit` method. ->**NOTE** - The `firstWhereOrNull` method is from the [collection](https://pub.dev/packages/collection) package. Add it to your `pubspec.yaml` dependencies and import with `import 'package:collection/collection.dart';` +> **Note:** The `firstWhereOrNull` method is from the [collection](https://pub.dev/packages/collection) package. Add it to your `pubspec.yaml` dependencies and import with `import 'package:collection/collection.dart';` {% tabs %} {% highlight dart %} @@ -54,47 +47,35 @@ import 'package:collection/collection.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ) - ) + child: Text('ID', overflow: TextOverflow.ellipsis), + ), ), GridColumn( columnName: 'name', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ) - ) + child: Text('Name', overflow: TextOverflow.ellipsis), + ), ), GridColumn( columnName: 'designation', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ) - ) + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), ), GridColumn( columnName: 'salary', label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ) - ) + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), ), - ] - ) + ], + ), ); } @@ -108,24 +89,48 @@ class EmployeeDataSource extends DataGridSource { /// Controls the editable text in the [TextField] widget TextEditingController editingController = TextEditingController(); + EmployeeDataSource({required List employeeData}) { + _employees = employeeData; + + dataGridRows = _employees.map((Employee employee) { + return DataGridRow( + cells: [ + DataGridCell(columnName: 'id', value: employee.id), + DataGridCell(columnName: 'name', value: employee.name), + DataGridCell( + columnName: 'designation', + value: employee.designation, + ), + DataGridCell(columnName: 'salary', value: employee.salary), + ], + ); + }).toList(); + } + /// List to store DataGridRow objects late List dataGridRows; @override - Future onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, - GridColumn column) async { - final dynamic oldValue = dataGridRow - .getCells() - .firstWhereOrNull((DataGridCell dataGridCell) => - dataGridCell.columnName == column.columnName) - ?.value ?? + Future onCellSubmit( + DataGridRow dataGridRow, + RowColumnIndex rowColumnIndex, + GridColumn column, + ) async { + final dynamic oldValue = + dataGridRow + .getCells() + .firstWhereOrNull( + (DataGridCell dataGridCell) => + dataGridCell.columnName == column.columnName, + ) + ?.value ?? ''; final int dataRowIndex = dataGridRows.indexOf(dataGridRow); - + if (newCellValue == null || oldValue == newCellValue) { return; } - + if (column.columnName == 'id') { dataGridRows[dataRowIndex].getCells()[rowColumnIndex.columnIndex] = DataGridCell(columnName: 'id', value: newCellValue); @@ -146,25 +151,50 @@ class EmployeeDataSource extends DataGridSource { } @override - Widget? buildEditWidget(DataGridRow dataGridRow, - RowColumnIndex rowColumnIndex, GridColumn column, CellSubmit submitCell) { + List get rows => dataGridRows; + + @override + DataGridRowAdapter buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: row.getCells().map((DataGridCell cell) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + alignment: (cell.columnName == 'id' || cell.columnName == 'salary') + ? Alignment.centerRight + : Alignment.centerLeft, + child: Text(cell.value.toString()), + ); + }).toList(), + ); + } + + @override + Widget? buildEditWidget( + DataGridRow dataGridRow, + RowColumnIndex rowColumnIndex, + GridColumn column, + CellSubmit submitCell, + ) { // Text going to display on editable widget - final String displayText = dataGridRow - .getCells() - .firstWhereOrNull((DataGridCell dataGridCell) => - dataGridCell.columnName == column.columnName) - ?.value - ?.toString() ?? + final String displayText = + dataGridRow + .getCells() + .firstWhereOrNull( + (DataGridCell dataGridCell) => + dataGridCell.columnName == column.columnName, + ) + ?.value + ?.toString() ?? ''; - + // The new cell value must be reset. // To avoid committing the [DataGridCell] value that was previously edited // into the current non-modified [DataGridCell]. newCellValue = null; - + final bool isNumericType = column.columnName == 'id' || column.columnName == 'salary'; - + return Container( padding: const EdgeInsets.all(8.0), alignment: isNumericType ? Alignment.centerRight : Alignment.centerLeft, @@ -203,11 +233,9 @@ class EmployeeDataSource extends DataGridSource { ![flutter datagrid editing](images/editing/datagrid_editing.gif) ->**NOTE** - The `TextEditingController` used in the example should be disposed to free up resources. Consider implementing disposal in your State class: `@override void dispose() { editingController.dispose(); super.dispose(); }` +> **Note:** The `TextEditingController` used in the example should be disposed to free up resources. Consider implementing disposal in your State class: `@override void dispose() { editingController.dispose(); super.dispose(); }` ->**NOTE** - Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). +> **Reference:** Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). ## Disable the editing for the specific column @@ -280,8 +308,7 @@ To disable the editing for a particular column, set the [GridColumn.allowEditing ![flutter datagrid disable the editing for specific column](images/editing/disable_editing.gif) ->**NOTE** - Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). +> **Note:** Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). ## Entering edit mode @@ -360,8 +387,7 @@ By default, a cell will enter edit mode when you double-tap it. To enable editin ## Methods ->**NOTE** - The editing lifecycle consists of three key methods: `onCellBeginEdit` (called when entering edit mode), `canSubmitCell` (called before exiting edit mode for validation), and `onCellSubmit` (called when changes are confirmed). All methods are asynchronous-capable. +> **Note:** The editing lifecycle consists of three key methods: `onCellBeginEdit` (called when entering edit mode), `canSubmitCell` (called before exiting edit mode for validation), and `onCellSubmit` (called when changes are confirmed). All methods are asynchronous-capable. ### onCellBeginEdit @@ -422,15 +448,13 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} ->**NOTE** - To display validation error messages to users, consider showing a snackbar or dialog in the `canSubmitCell` method when returning `false`, or use a validation field overlay on the edit widget in `buildEditWidget`. +> **Note:** To display validation error messages to users, consider showing a snackbar or dialog in the `canSubmitCell` method when returning `false`, or use a validation field overlay on the edit widget in `buildEditWidget`. ### onCellSubmit The [DataGridSource.onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) method is called when the editing is completed and validation passes. This is an asynchronous method where you should save the edited values to your underlying data collection. The UI automatically refreshes after changes are committed. ->**NOTE** - There is no need to call the `notifyListeners` after you update the DataGridRows. DataGrid will refresh the UI automatically. +> **Note:** There is no need to call the `notifyListeners` after you update the DataGridRows. DataGrid will refresh the UI automatically. {% tabs %} {% highlight dart %} @@ -479,8 +503,7 @@ class EmployeeDataSource extends DataGridSource { The [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) method is called when editing is cancelled. This occurs when the `Esc` key is pressed on Web and Desktop platforms. When this method is called, the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) and [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) methods are not called. Focus returns to the DataGrid after cancellation. ->**NOTE** - You do not need to call `notifyListeners` inside this method as the UI automatically handles state updates. +> **Note:** You do not need to call `notifyListeners` inside this method as the UI automatically handles state updates. {% tabs %} {% highlight dart %} @@ -583,8 +606,7 @@ The SfDataGrid allows moving the cell into edit mode programmatically by calling ![flutter datagrid begin edit](images/editing/begin_editing.gif) ->**NOTE** - Download the complete programmatic editing demo from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). +> **Note:** Download the complete programmatic editing demo from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-editing-in-flutter-datatable-sfdatagrid). ### EndEdit @@ -844,6 +866,7 @@ The following example shows how to display a loading indicator during asynchrono import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'dart:async'; +import 'package:collection/collection.dart'; /// Global StreamController to manage loading state during async operations StreamController loadingController = StreamController(); @@ -974,5 +997,4 @@ class _MyHomePageState extends State { {% endhighlight %} {% endtabs %} ->**NOTE** - The `StreamController` pattern is used here to manage UI state during async operations. The loading indicator is shown/hidden by emitting values to the stream. You can also use state management solutions like `Provider`, `Riverpod`, or `Bloc` for more complex scenarios. +> **Note:** The `StreamController` pattern is used here to manage UI state during async operations. The loading indicator is shown/hidden by emitting values to the stream. You can also use state management solutions like `Provider`, `Riverpod`, or `Bloc` for more complex scenarios. diff --git a/Flutter/datagrid/filtering.md b/Flutter/datagrid/filtering.md index ae6fcc42c..6a523990c 100644 --- a/Flutter/datagrid/filtering.md +++ b/Flutter/datagrid/filtering.md @@ -11,15 +11,11 @@ documentation: ug Filtering is the process of fetching values from a collection that satisfy specified conditions. In the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html), filtering can be applied both through the UI and programmatically. -> **NOTE** - This feature requires the `syncfusion_flutter_datagrid` package version 20.2.38 or later. Ensure that you have added the package to your `pubspec.yaml` file. - ## Programmatic Filtering The SfDataGrid allows you to filter the data rows programmatically by adding filter conditions along with their respective column names to the [DataGridSource.filterConditions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/filterConditions.html) map collection. In the map collection, the `key` defines the [columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/columnName.html) and the `values` define the list of [FilterCondition](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterCondition-class.html). -> **NOTE** - To use programmatic filtering, you must have a custom class that extends [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) with properly initialized data rows. +> **Note:** To use programmatic filtering, you must have a custom class that extends [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) with properly initialized data rows. `DataGridSource.filterConditions` is an unmodifiable map collection. So, it doesn't allow us to perform CRUD operations directly in the `DataGridSource.filterConditions` property. However, it can be done by the following public methods: @@ -535,8 +531,8 @@ After filtering, you can retrieve the rows in the same order as displayed in the `SfDataGrid` provides an Excel-like filtering UI and an advanced filter UI for easy data filtering. UI filtering can be enabled by setting the [SfDataGrid.allowFiltering](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowFiltering.html) property to `true`. This allows the filter UI to be opened by clicking the filter icon in the column header. -> **NOTE** - **Platform-specific behavior:** The filtering UI appears as a popup menu on desktop and web platforms, and as a new page on mobile platforms. +> **Note:** +> - **Platform-specific behavior:** The filtering UI appears as a popup menu on desktop and web platforms, and as a new page on mobile platforms. The `SfDataGrid` provides the following types of filter UI modes: @@ -627,57 +623,47 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - allowFiltering: true, - source: employeeDataSource, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - allowFiltering: false, - columnName: 'ID', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, + return Scaffold( + body: SfDataGrid( + allowFiltering: true, + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + allowFiltering: false, + columnName: 'ID', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), ), ), - ), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), ), ), - ), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), ), ), - ), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), ), ), - ), - ], + ], + ), ); } @@ -699,63 +685,53 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - allowFiltering: true, - source: employeeDataSource, - onFilterChanging: (DataGridFilterChangeDetails details) { - // Restrict filtering on the Salary column - if (details.column.columnName == 'Salary') { - return false; - } - return true; - }, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + allowFiltering: true, + onFilterChanging: (DataGridFilterChangeDetails details) { + // Restrict filtering on the Salary column + if (details.column.columnName == 'salary') { + return false; + } + return true; + }, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), ), ), - ), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), ), ), - ), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), ), ), - ), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), ), ), - ), - ], + ], + ), ); } @@ -773,63 +749,53 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { - return SfDataGrid( - allowFiltering: true, - source: employeeDataSource, - onFilterChanged: (DataGridFilterChangeDetails details) { - debugPrint('Column Name: ${details.column.columnName}'); - if (details.filterConditions.isNotEmpty) { - debugPrint('Filter Type: ${details.filterConditions.last.type}'); - debugPrint('Filter Value: ${details.filterConditions.last.value}'); - } - }, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + allowFiltering: true, + onFilterChanged: (DataGridFilterChangeDetails details) { + debugPrint('Column Name: ${details.column.columnName}'); + if (details.filterConditions.isNotEmpty) { + debugPrint('Filter Type: ${details.filterConditions.last.type}'); + debugPrint('Filter Value: ${details.filterConditions.last.value}'); + } + }, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), ), ), - ), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), ), ), - ), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), ), ), - ), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), ), ), - ), - ], + ], + ), ); } @@ -840,8 +806,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; The `SfDataGrid` provides support to customize the behavior and appearance of the filter popup menu. The following subsections demonstrate how to customize various aspects of the filter UI. -> **NOTE** - Filter UI customization options like `filterMode`, `canShowSortingOptions`, and `canShowClearFilterOption` are available through the [FilterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterPopupMenuOptions-class.html) class in the [GridColumn.filterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/filterPopupMenuOptions.html) property. +> **Note:** Filter UI customization options like `filterMode`, `canShowSortingOptions`, and `canShowClearFilterOption` are available through the [FilterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/FilterPopupMenuOptions-class.html) class in the [GridColumn.filterPopupMenuOptions](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/filterPopupMenuOptions.html) property. ### Show checkbox or advanced filtering mode @@ -1181,8 +1146,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; The `SfDataGrid` allows you to change the filter icon by using the [SfDataGridThemeData.filterIcon](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterIcon.html) property. The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. -> **NOTE** - Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply custom filter icons. Use a [Builder](https://api.flutter.dev/flutter/widgets/Builder-class.html) widget to return different icons based on filter states (filtered or not filtered). +> **Note:** Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply custom filter icons. Use a [Builder](https://api.flutter.dev/flutter/widgets/Builder-class.html) widget to return different icons based on filter states (filtered or not filtered). {% tabs %} {% highlight Dart %} @@ -1338,8 +1302,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; The text style of the filter popup menu can be customized by using the [SfDataGridThemeData.filterPopupTextStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterPopupTextStyle.html) and [SfDataGridThemeData.filterPopupDisabledTextStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/filterPopupDisabledTextStyle.html) properties. -> **NOTE** - Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply text style customizations. +> **Note:** Wrap the `SfDataGrid` inside an `SfDataGridTheme` widget to apply text style customizations. {% tabs %} {% highlight Dart %} @@ -1362,7 +1325,7 @@ import 'package:syncfusion_flutter_core/theme.dart'; ), ), child: SfDataGrid( - source: employeeDataSource, + source: _employeeDataSource, allowFiltering: true, columnWidthMode: ColumnWidthMode.fill, columns: [ @@ -1371,10 +1334,7 @@ import 'package:syncfusion_flutter_core/theme.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ), + child: Text('ID', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -1382,10 +1342,7 @@ import 'package:syncfusion_flutter_core/theme.dart'; label: Container( padding: EdgeInsets.symmetric(horizontal: 8.0), alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ), + child: Text('Name', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -1393,10 +1350,7 @@ import 'package:syncfusion_flutter_core/theme.dart'; label: Container( padding: EdgeInsets.all(8.0), alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ), + child: Text('Designation', overflow: TextOverflow.ellipsis), ), ), GridColumn( @@ -1564,8 +1518,7 @@ By default, the `FilterBehavior.strongDataType` applies to numeric, String, and The `SfDataGrid` provides complete color customization support for the filter popup menu, allowing you to personalize its appearance and enhance its visual appeal. -> **NOTE** - The `SfDataGrid` must be wrapped inside an `SfDataGridTheme` widget for appearance customizations to take effect. The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. +> **Note:** The `SfDataGrid` must be wrapped inside an `SfDataGridTheme` widget for appearance customizations to take effect. The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. | Properties | Description | @@ -1605,8 +1558,7 @@ The `SfDataGrid` provides complete color customization support for the filter po | `searchAreaFocusedBorderColor` | Use the [SfDataGridThemeData.searchAreaFocusedBorderColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/searchAreaFocusedBorderColor.html) property to define the focused border color of the search area in the filter popup menu | | `searchIconColor` | The color of the search icon in the search area of the filter popup menu can be customized using the [SfDataGridThemeData.searchIconColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/searchIconColor.html) property. | -> **NOTE** - The `cancelFilteringLabelColor`, `filterPopupBottomDividerColor`, and `okFilteringLabelColor` properties are supported only on desktop platforms. +> **Note:** The `cancelFilteringLabelColor`, `filterPopupBottomDividerColor`, and `okFilteringLabelColor` properties are supported only on desktop platforms. The following example shows how to customize the filter popup menu using properties from `SfDataGridTheme`, such as `cancelFilteringLabelButtonColor`, `cancelFilteringLabelColor`, `okFilteringLabelButtonColor`, `okFilteringLabelColor`, `filterPopupCheckboxFillColor`, and `filterPopupDisabledIconColor`. diff --git a/Flutter/datagrid/grouping.md b/Flutter/datagrid/grouping.md index 49f2c5230..47921589d 100644 --- a/Flutter/datagrid/grouping.md +++ b/Flutter/datagrid/grouping.md @@ -31,8 +31,8 @@ The following code demonstrates how to apply grouping to a column: {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class SfDataGridDemoState extends State { List employees = []; @@ -139,28 +139,19 @@ To disable column grouping for a particular column, remove that `ColumnGroup` in {% highlight Dart %} import 'package:collection/collection.dart'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -class SfDataGridDemoState extends State { List employees = []; late EmployeeDataSource employeeDataSource; - @override - void initState() { - super.initState(); - employees = getEmployeeData(); - employeeDataSource = EmployeeDataSource(employeeData: employees); - employeeDataSource - .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true)); - employeeDataSource - .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: false)); - } - @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: Column(children: [ - ElevatedButton( + body: Column( + children: [ + ElevatedButton( onPressed: () { setState(() {}); ColumnGroup? group = employeeDataSource.groupedColumns @@ -169,39 +160,50 @@ class SfDataGridDemoState extends State { employeeDataSource.removeColumnGroup(group); } }, - child: Text('Remove Salary Column Group')), - Expanded( + child: Text('Remove Salary Column Group'), + ), + Expanded( child: SfDataGrid( - source: employeeDataSource, - allowExpandCollapseGroup: true, - columns: [ - GridColumn( + source: employeeDataSource, + allowExpandCollapseGroup: true, + columns: [ + GridColumn( columnName: 'ID', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'Name', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'Designation', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Designation', - overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'Salary', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Salary'))), - ])), - ]), + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ), + ], + ), ); } @@ -215,6 +217,9 @@ To clear all the column groups, simply call the [DataGridSource.clearColumnGroup {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; + class SfDataGridDemoState extends State { List employees = []; late EmployeeDataSource employeeDataSource; @@ -224,55 +229,72 @@ class SfDataGridDemoState extends State { super.initState(); employees = getEmployeeData(); employeeDataSource = EmployeeDataSource(employeeData: employees); - employeeDataSource - .addColumnGroup(ColumnGroup(name: 'Designation', sortGroupRows: true)); - employeeDataSource - .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: false)); + employeeDataSource.addColumnGroup( + ColumnGroup(name: 'Designation', sortGroupRows: true), + ); + employeeDataSource.addColumnGroup( + ColumnGroup(name: 'Salary', sortGroupRows: false), + ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: Column(children: [ - ElevatedButton( + body: Column( + children: [ + ElevatedButton( onPressed: () { setState(() {}); employeeDataSource.clearColumnGroups(); }, - child: const Text('Clear all column groups')), - Expanded( + child: const Text('Clear all column groups'), + ), + Expanded( child: SfDataGrid( - source: employeeDataSource, - allowExpandCollapseGroup: true, - columns: [ - GridColumn( + source: employeeDataSource, + allowExpandCollapseGroup: true, + columns: [ + GridColumn( columnName: 'ID', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: const Text('ID'))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: const Text('ID'), + ), + ), + GridColumn( columnName: 'Name', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: const Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: const Text('Name'), + ), + ), + GridColumn( columnName: 'Designation', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: const Text('Designation', - overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: const Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ), + ), + ), + GridColumn( columnName: 'Salary', label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: const Text('Salary'))), - ])), - ]), + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: const Text('Salary'), + ), + ), + ], + ), + ), + ], + ), ); } } @@ -584,8 +606,9 @@ class SfDataGridDemoState extends State { super.initState(); employees = getEmployeeData(); employeeDataSource = EmployeeDataSource(employeeData: employees); - employeeDataSource - .addColumnGroup(ColumnGroup(name: 'Salary', sortGroupRows: true)); + employeeDataSource.addColumnGroup( + ColumnGroup(name: 'Salary', sortGroupRows: true), + ); } @override @@ -593,35 +616,43 @@ class SfDataGridDemoState extends State { return Scaffold( appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), body: SfDataGrid( - source: employeeDataSource, - allowExpandCollapseGroup: true, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: - Text('Designation', overflow: TextOverflow.ellipsis))), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Salary'))), - ]), + source: employeeDataSource, + allowExpandCollapseGroup: true, + columns: [ + GridColumn( + columnName: 'ID', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), ); } } @@ -629,13 +660,19 @@ class SfDataGridDemoState extends State { class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { dataGridRows = employeeData - .map((e) => DataGridRow(cells: [ + .map( + (e) => DataGridRow( + cells: [ DataGridCell(columnName: 'ID', value: e.id), DataGridCell(columnName: 'Name', value: e.name), DataGridCell( - columnName: 'Designation', value: e.designation), + columnName: 'Designation', + value: e.designation, + ), DataGridCell(columnName: 'Salary', value: e.salary), - ])) + ], + ), + ) .toList(); } @@ -647,23 +684,25 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((e) { - return Container( - alignment: Alignment.center, - padding: EdgeInsets.all(8), - child: Text( - e.value.toString(), - ), - ); - }).toList()); + cells: row.getCells().map((e) { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.all(8), + child: Text(e.value.toString()), + ); + }).toList(), + ); } @override Widget? buildGroupCaptionCellWidget( - RowColumnIndex rowColumnIndex, String summaryValue) { + RowColumnIndex rowColumnIndex, + String summaryValue, + ) { return Container( - padding: EdgeInsets.symmetric(horizontal: 12, vertical: 15), - child: Text(summaryValue)); + padding: EdgeInsets.symmetric(horizontal: 12, vertical: 15), + child: Text(summaryValue), + ); } @override @@ -673,10 +712,11 @@ class EmployeeDataSource extends DataGridSource { .getCells() .whereType>() .firstWhereOrNull( - (DataGridCell cell) => cell.columnName == columnName); - - if (salaryCell != null) { - final double total = salaryCell.value; + (DataGridCell cell) => cell.columnName == columnName, + ); + + if (salaryCell != null && salaryCell.value != null) { + final double total = salaryCell.value!; if (total > 100000 && total <= 200000) { return '> 100 K & <= 200 K'; } else if (total > 90000 && total <= 100000) { @@ -837,80 +877,93 @@ The following code example demonstrates how to use these methods: {% tabs %} {% highlight Dart %} -final DataGridController _dataGridController = DataGridController(); + List _employees = []; + late EmployeeDataSource _employeeDataSource; + final DataGridController _dataGridController = DataGridController(); + + @override + void initState() { + super.initState(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); + _employeeDataSource.addColumnGroup( + ColumnGroup(name: 'Designation', sortGroupRows: true), + ); + _employeeDataSource.addColumnGroup( + ColumnGroup(name: 'Salary', sortGroupRows: false), + ); + } -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: Column(children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: Column( children: [ - ElevatedButton( - onPressed: () { - _dataGridController.expandAllGroup(); - }, - child: const Text('Expand All'), - ), - ElevatedButton( - onPressed: () { - _dataGridController.collapseAllGroup(); - }, - child: const Text('Collapse All'), - ), - ElevatedButton( - onPressed: () { - _dataGridController.expandGroupsAtLevel(0); - }, - child: const Text('Expand Level 0'), - ), - ], - ), - Expanded( - child: SfDataGrid( - controller: _dataGridController, - source: employeeDataSource, - allowExpandCollapseGroup: true, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('ID'), - ), - ), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Name'), - ), - ), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Designation', overflow: TextOverflow.ellipsis), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + onPressed: () { + _dataGridController.expandAllGroup(); + }, + child: const Text('Expand All'), ), - ), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.all(8), - alignment: Alignment.center, - child: Text('Salary'), + ElevatedButton( + onPressed: () { + _dataGridController.collapseAllGroup(); + }, + child: const Text('Collapse All'), ), + ], + ), + Expanded( + child: SfDataGrid( + controller: _dataGridController, + source: _employeeDataSource, + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + allowExpandCollapseGroup: true, + columns: [ + GridColumn( + columnName: 'ID', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.all(8), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], ), - ], - ), + ), + ], ), - ]), - ); -} + ); + } {% endhighlight %} {% endtabs %} From d8cb1fd0bbfd5840ed1cabbcfbf6741a5d717308 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Tue, 7 Jul 2026 19:24:44 +0530 Subject: [PATCH 09/18] FLUT-1038842-[others][flutter]: Till Summaries fixed --- Flutter/datagrid/selection.md | 281 ++++++++------- Flutter/datagrid/summaries.md | 626 ++++++++++++++++++---------------- 2 files changed, 474 insertions(+), 433 deletions(-) diff --git a/Flutter/datagrid/selection.md b/Flutter/datagrid/selection.md index 2f86f25f5..00ece32d4 100644 --- a/Flutter/datagrid/selection.md +++ b/Flutter/datagrid/selection.md @@ -12,9 +12,9 @@ This section explains how to enable selection in the Datagrid; modes, properties The Datagrid allows you to select a specific row or group of rows either programmatically or by touch interactions. To enable selection, set the [selectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionMode.html) property of the SfDataGrid to a value other than `none`. The default value is `none`. SfDataGrid has different selection modes to perform the selection operation as follows. -N> The [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) property must be initialized in the [source](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/source.html). The `rows` is the collection of `DataGridRow` to populate the rows in DataGrid. - -N> Import the [SelectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SelectionMode.html) enum from the `syncfusion_flutter_datagrid` package to use different selection modes in your application. +> **Note:** +>- The [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) property must be initialized in the [source](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/source.html). The `rows` is the collection of `DataGridRow` to populate the rows in DataGrid. +>- Import the [SelectionMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SelectionMode.html) enum from the `syncfusion_flutter_datagrid` package to use different selection modes in your application. ## Selection modes @@ -220,7 +220,7 @@ When using `multiple`, you can select multiple rows by pressing the key modifier ![flutter datagrid shows multiple row selection](images/selection/flutter-datagrid-multiple-selection.png) -N> When the `selectionMode` is `multiple`, multiple rows can be selected or deselected by clicking the respective rows. In multiple selections, pressing the navigation keys will move the current cell alone. The rows can be selected or deselected by pressing the Space key. +> **Note:** When the `selectionMode` is `multiple`, multiple rows can be selected or deselected by clicking the respective rows. In multiple selections, pressing the navigation keys will move the current cell alone. The rows can be selected or deselected by pressing the Space key. ### Single deselect row selection @@ -232,47 +232,45 @@ The `singleDeselect` mode allows selection of only one row at a time. Unlike the @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - selectionMode: SelectionMode.singleDeselect)); + body: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + selectionMode: SelectionMode.singleDeselect, + ), + ); } {% endhighlight %} @@ -336,13 +334,13 @@ The selection can be disabled by setting the `selectionMode` property as `none`. Selection on a particular row can be disabled by handling the [onCurrentCellActivating](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onCurrentCellActivating.html) callback. - N> You cannot select the header row of SfDataGrid. +> **Note:** You cannot select the header row of SfDataGrid. ## Getting selected rows Get the information of the selected rows by using the [controller](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/controller.html) property. Create an instance of the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) and set it to the controller property. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) property returns the selected DataGridRow and the [selectedIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedIndex.html) property returns the index of the [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) in SfDataGrid. The [selectedRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRow.html) denotes the last selected row in multiple selections. -N> [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) objects are expected to be long-lived, not re-created with each build. Instantiate the controller at the class level in your State class to maintain its state across widget rebuilds. +> **Note:** [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) objects are expected to be long-lived, not re-created with each build. Instantiate the controller at the class level in your State class to maintain its state across widget rebuilds. {% tabs %} {% highlight Dart %} @@ -920,7 +918,7 @@ The following code example shows how to clear selection when the `selectionMode` {% endhighlight %} {% endtabs %} -N> Selected rows and selections will be cleared whenever the `dataSource` is changed at runtime. +> **Note:** Selected rows and selections will be cleared whenever the `dataSource` is changed at runtime. ## Keyboard behavior @@ -1109,65 +1107,64 @@ The following example shows how to cancel the selection when selecting a row tha @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - selectionMode: SelectionMode.single, - onSelectionChanging: - (List addedRows, List removedRows) { - if (addedRows.isNotEmpty) { - final index = _employeeDataSource.dataGridRows.indexOf(addedRows.last); - if (index >= 0 && index < _employees.length) { - Employee employee = _employees[index]; - if (employee.designation == 'Manager') { - return false; - } - } - } - return true; - }, - onSelectionChanged: - (List addedRows, List removedRows) { - // Handle selection change - }, - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + selectionMode: SelectionMode.single, + onSelectionChanging: + (List addedRows, List removedRows) { + if (addedRows.isNotEmpty) { + final index = _employeeDataSource._employeeData.indexOf( + addedRows.last, + ); + if (index >= 0 && index < _employees.length) { + Employee employee = _employees[index]; + if (employee.designation == 'Manager') { + return false; + } + } + } + return true; + }, + onSelectionChanged: + (List addedRows, List removedRows) { + // Handle selection change + }, + ), + ); } {% endhighlight %} @@ -1401,7 +1398,7 @@ To retrieve the details of a row in the DataGrid, use the [controller](https://p To perform custom actions beyond the default keyboard behavior mentioned in the keyboard behavior table, create a custom selection manager by overriding the [handleKeyEvent()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowSelectionManager/handleKeyEvent.html) method of the [RowSelectionManager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowSelectionManager-class.html) class and assign it to the [SfDataGrid.selectionManager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionManager.html) property. -N> Import [services](https://api.flutter.dev/flutter/services/services-library.html) and [foundation](https://api.flutter.dev/flutter/foundation/foundation-library.html) packages from Flutter to use `LogicalKeyboardKey` and `HardwareKeyboard`. +> **Note:** Import [services](https://api.flutter.dev/flutter/services/services-library.html) and [foundation](https://api.flutter.dev/flutter/foundation/foundation-library.html) packages from Flutter to use `LogicalKeyboardKey` and `HardwareKeyboard`. The following example demonstrates how to implement a custom action for the Ctrl + A key combination: @@ -1409,7 +1406,7 @@ The following example demonstrates how to implement a custom action for the Enter key moves the current cell to the next focused row of the same column. You can customize this behavior by overriding the `handleKeyEvent()` method in a custom [RowSelectionManager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/RowSelectionManager-class.html). @@ -1486,62 +1483,60 @@ By default, pressing the Enter key moves the current cell to the next {% highlight Dart %} import 'package:flutter/services.dart'; -import 'package:flutter/foundation.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - final CustomSelectionManager _customSelectionManager = CustomSelectionManager(); + final CustomSelectionManager _customSelectionManager = + CustomSelectionManager(); @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( + body: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - selectionMode: SelectionMode.multiple, - navigationMode: GridNavigationMode.cell, - selectionManager: _customSelectionManager, - )); + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + selectionMode: SelectionMode.multiple, + navigationMode: GridNavigationMode.cell, + selectionManager: _customSelectionManager, + ), + ); } class CustomSelectionManager extends RowSelectionManager { @override - void handleKeyEvent(KeyEvent keyEvent) { + Future handleKeyEvent(KeyEvent keyEvent) async { if (keyEvent.logicalKey == LogicalKeyboardKey.enter) { // Apply custom logic for Enter key return; @@ -1558,7 +1553,7 @@ class CustomSelectionManager extends RowSelectionManager { You can customize the appearance of selected rows and the current cell by using the [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html) and [SfDataGridThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData-class.html) classes. All styles such as [selectionColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/selectionColor.html) and [DataGridCurrentCellStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/DataGridCurrentCellStyle-class.html) are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. -N> Import `package:syncfusion_flutter_core/theme.dart` to access the theming classes. +> **Note:** Import `package:syncfusion_flutter_core/theme.dart` to access the theming classes. ### Selection @@ -1753,4 +1748,4 @@ import 'package:syncfusion_flutter_core/theme.dart'; ![flutter datagrid shows customized current cell](images/selection/flutter-datagrid-customized-currentcell.png) -N> When [navigationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) is set to [GridNavigationMode.row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridNavigationMode.html), the `currentCellStyle` property customizes the current row border's color instead of individual cell borders. +> **Note:** When [navigationMode](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/navigationMode.html) is set to [GridNavigationMode.row](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridNavigationMode.html), the `currentCellStyle` property customizes the current row border's color instead of individual cell borders. diff --git a/Flutter/datagrid/summaries.md b/Flutter/datagrid/summaries.md index 584099408..6b4076939 100644 --- a/Flutter/datagrid/summaries.md +++ b/Flutter/datagrid/summaries.md @@ -9,8 +9,6 @@ documentation: ug # Summaries in Flutter DataGrid (SfDataGrid) -> **NOTE**: Ensure you have added `syncfusion_flutter_datagrid` package to your `pubspec.yaml` file and imported the necessary packages in your Dart file. - ## Table summary The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides built-in support to display concise information about the rows by using the table summary rows. The table summary value is calculated based on all the rows in the [DataGridSource.rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) property. You can add a table summary row to the DataGrid by adding the [GridTableSummaryRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridTableSummaryRow-class.html) to the [SfDataGrid.tableSummaryRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/tableSummaryRows.html) collection. @@ -24,17 +22,12 @@ The summary information can be displayed in a row by setting the [GridTableSumma {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class Employee { - Employee({ - required this.id, - required this.name, - required this.designation, - required this.salary, - }); - + Employee(this.id, this.name, this.designation, this.salary); + final int id; final String name; final String designation; @@ -44,13 +37,19 @@ class Employee { class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { _employeeData = employeeData - .map((e) => DataGridRow(cells: [ + .map( + (e) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: e.id), DataGridCell(columnName: 'name', value: e.name), DataGridCell( - columnName: 'designation', value: e.designation), + columnName: 'designation', + value: e.designation, + ), DataGridCell(columnName: 'salary', value: e.salary), - ])) + ], + ), + ) .toList(); } @@ -61,84 +60,85 @@ class EmployeeDataSource extends DataGridSource { @override Widget? buildTableSummaryCellWidget( - GridTableSummaryRow summaryRow, - GridSummaryColumn? summaryColumn, - RowColumnIndex rowColumnIndex, - String summaryValue) { - return Container( - padding: EdgeInsets.all(15.0), - child: Text(summaryValue), - ); + GridTableSummaryRow summaryRow, + GridSummaryColumn? summaryColumn, + RowColumnIndex rowColumnIndex, + String summaryValue, + ) { + return Container(padding: EdgeInsets.all(15.0), child: Text(summaryValue)); } @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((e) { - return Container( - alignment: Alignment.center, - padding: EdgeInsets.all(8.0), - child: Text(e.value.toString()), - ); - }).toList()); + cells: row.getCells().map((e) { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.all(8.0), + child: Text(e.value.toString()), + ); + }).toList(), + ); } } -@override -Widget build(BuildContext context) { - final List employees = [ - Employee(id: 1, name: 'John', designation: 'Developer', salary: 50000), - Employee(id: 2, name: 'Jane', designation: 'Manager', salary: 60000), - // Add more employees - ]; - - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( showSummaryInRow: true, title: 'Total Salary: {Sum} for 20 employees', columns: [ GridSummaryColumn( - name: 'Sum', - columnName: 'salary', - summaryType: GridSummaryType.sum) + name: 'Sum', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.bottom) - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} @@ -156,54 +156,62 @@ The summary information can be displayed in a column by setting the `GridTableSu {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( showSummaryInRow: false, columns: [ GridSummaryColumn( - name: 'Sum', - columnName: 'salary', - summaryType: GridSummaryType.sum), + name: 'Sum', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.bottom) - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} @@ -217,64 +225,74 @@ The table summary row can be shown at either the top or bottom position by using {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( showSummaryInRow: false, columns: [ GridSummaryColumn( - name: 'Sum', - columnName: 'salary', - summaryType: GridSummaryType.sum) + name: 'Sum', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.top), - GridTableSummaryRow( + position: GridTableSummaryRowPosition.top, + ), + GridTableSummaryRow( showSummaryInRow: true, title: 'Total Salary: {Sum} for 20 employees', columns: [ GridSummaryColumn( - name: 'Sum', - columnName: 'salary', - summaryType: GridSummaryType.sum) + name: 'Sum', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.bottom) - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} @@ -298,60 +316,69 @@ The SfDataGrid supports displaying a summary title along with column summary val {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( showSummaryInRow: false, title: 'Total Employee Count: {Count}', titleColumnSpan: 3, columns: [ GridSummaryColumn( - name: 'Count', - columnName: 'id', - summaryType: GridSummaryType.count), + name: 'Count', + columnName: 'id', + summaryType: GridSummaryType.count, + ), GridSummaryColumn( - name: 'Sum', - columnName: 'salary', - summaryType: GridSummaryType.sum) + name: 'Sum', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.bottom), - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} @@ -365,56 +392,64 @@ The background color of the table summary row can be customized by using the [Gr {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( color: Colors.indigo, showSummaryInRow: true, title: 'Minimum Salary: {Minimum} for 20 employees', columns: [ GridSummaryColumn( - name: 'Minimum', - columnName: 'salary', - summaryType: GridSummaryType.minimum) + name: 'Minimum', + columnName: 'salary', + summaryType: GridSummaryType.minimum, + ), ], - position: GridTableSummaryRowPosition.bottom), - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} @@ -438,13 +473,19 @@ import 'package:flutter/material.dart'; class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { _employeeData = employeeData - .map((e) => DataGridRow(cells: [ + .map( + (e) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: e.id), DataGridCell(columnName: 'name', value: e.name), DataGridCell( - columnName: 'designation', value: e.designation), + columnName: 'designation', + value: e.designation, + ), DataGridCell(columnName: 'salary', value: e.salary), - ])) + ], + ), + ) .toList(); } @@ -454,14 +495,18 @@ class EmployeeDataSource extends DataGridSource { List get rows => _employeeData; @override - String calculateSummaryValue(GridTableSummaryRow summaryRow, - GridSummaryColumn? summaryColumn, RowColumnIndex rowColumnIndex) { + String calculateSummaryValue( + GridTableSummaryRow summaryRow, + GridSummaryColumn? summaryColumn, + RowColumnIndex rowColumnIndex, + ) { List getCellValues(GridSummaryColumn summaryColumn) { final List values = []; for (final DataGridRow row in rows) { final DataGridCell? cell = row.getCells().firstWhereOrNull( - (DataGridCell element) => - element.columnName == summaryColumn.columnName); + (DataGridCell element) => + element.columnName == summaryColumn.columnName, + ); if (cell != null && cell.value != null) { values.add(cell.value as int); } @@ -473,7 +518,7 @@ class EmployeeDataSource extends DataGridSource { if (title != null) { if (summaryRow.showSummaryInRow && summaryRow.columns.isNotEmpty) { for (final GridSummaryColumn summaryColumn in summaryRow.columns) { - if (title.contains(summaryColumn.name)) { + if (title!.contains(summaryColumn.name)) { double deviation = 0; final List values = getCellValues(summaryColumn); if (values.isNotEmpty) { @@ -485,7 +530,9 @@ class EmployeeDataSource extends DataGridSource { deviation = sqrt(variance / (values.length - 1)); } title = title.replaceAll( - '{${summaryColumn.name}}', deviation.toStringAsFixed(2)); + '{${summaryColumn.name}}', + deviation.toStringAsFixed(2), + ); } } } @@ -495,88 +542,87 @@ class EmployeeDataSource extends DataGridSource { @override Widget? buildTableSummaryCellWidget( - GridTableSummaryRow summaryRow, - GridSummaryColumn? summaryColumn, - RowColumnIndex rowColumnIndex, - String summaryValue) { - return Container( - padding: EdgeInsets.all(15.0), - child: Text(summaryValue), - ); + GridTableSummaryRow summaryRow, + GridSummaryColumn? summaryColumn, + RowColumnIndex rowColumnIndex, + String summaryValue, + ) { + return Container(padding: EdgeInsets.all(15.0), child: Text(summaryValue)); } @override DataGridRowAdapter buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((e) { - return Container( - alignment: Alignment.center, - padding: EdgeInsets.all(8.0), - child: Text(e.value.toString()), - ); - }).toList()); + cells: row.getCells().map((e) { + return Container( + alignment: Alignment.center, + padding: EdgeInsets.all(8.0), + child: Text(e.value.toString()), + ); + }).toList(), + ); } } -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: SfDataGrid( - source: EmployeeDataSource(employeeData: employees), - tableSummaryRows: [ - GridTableSummaryRow( + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + tableSummaryRows: [ + GridTableSummaryRow( showSummaryInRow: true, title: 'Standard Deviation: {Deviation}', columns: [ GridSummaryColumn( - name: 'Deviation', - columnName: 'salary', - summaryType: GridSummaryType.sum) + name: 'Deviation', + columnName: 'salary', + summaryType: GridSummaryType.sum, + ), ], - position: GridTableSummaryRowPosition.bottom), - ], - columns: [ - GridColumn( + position: GridTableSummaryRowPosition.bottom, + ), + ], + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Job Title', overflow: TextOverflow.ellipsis))), - GridColumn( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Job Title', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ], - ), - ); -} + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ); + } {% endhighlight %} {% endtabs %} ![flutter datagrid shows custom logic for table summary column](images/summaries/flutter-datagrid-summary-column-custom-logic.png) - -## See also - -* [Syncfusion Flutter DataGrid Documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) -* [GridTableSummaryRow API](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridTableSummaryRow-class.html) -* [GridSummaryColumn API](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridSummaryColumn-class.html) -* [GridSummaryType Enum](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridSummaryType.html) -* [DataGridSource API](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) From bbbe025f48866f322f16cbe15fe1ec107ee3a5de Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 12:01:53 +0530 Subject: [PATCH 10/18] FLUT-1038842-[others][flutter]: Till PulltoRefresh fixed --- Flutter/datagrid/columns-resizing.md | 20 +- Flutter/datagrid/footer.md | 61 +--- Flutter/datagrid/freeze-panes.md | 160 ++++----- Flutter/datagrid/load-more.md | 504 +++++++++++++------------- Flutter/datagrid/placeholder.md | 10 +- Flutter/datagrid/pull-to-refresh.md | 509 +++++++++++++++------------ Flutter/datagrid/styles.md | 16 +- Flutter/datagrid/swiping.md | 483 +++++++++++++------------ 8 files changed, 893 insertions(+), 870 deletions(-) diff --git a/Flutter/datagrid/columns-resizing.md b/Flutter/datagrid/columns-resizing.md index 7201bfdd0..661c3c42c 100644 --- a/Flutter/datagrid/columns-resizing.md +++ b/Flutter/datagrid/columns-resizing.md @@ -11,15 +11,11 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support to resize the columns by dragging the right end of the column header. The column resizing can be enabled by setting the [SfDataGrid.allowColumnsResizing](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowColumnsResizing.html) property to `true`. ->**Note** ->Ensure you have added the `syncfusion_flutter_datagrid` package to your project. For setup instructions, refer to the [getting started](getting-started.md) documentation. - `SfDataGrid` does not automatically resize the columns when you perform column resizing. You should maintain the column width collection at the application level and set the column width of the corresponding column using the [SfDataGrid.onColumnResizeUpdate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onColumnResizeUpdate.html) callback. The column resizing indicator appears based on the platform. In web and desktop platforms, the indicator appears when you hover over the right end of the column and drag it. In mobile platforms, the indicator comes into view when you long-press the corresponding column header. -> **NOTE:** -> Column resizing considers the [GridColumn.minimumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/minimumWidth.html) and [GridColumn.maximumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/maximumWidth.html) properties. These limits are enforced to prevent columns from becoming too small or too large during resizing. +> **Note:** Column resizing considers the [GridColumn.minimumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/minimumWidth.html) and [GridColumn.maximumWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn/maximumWidth.html) properties. These limits are enforced to prevent columns from becoming too small or too large during resizing. ## Basic Column Resizing @@ -532,23 +528,11 @@ To prevent a column from being hidden while resizing, use the `GridColumn.minimu {% endhighlight %} {% endtabs %} -## Troubleshooting - -**Column widths not persisting after app restart?** -Column width changes are stored in memory during the session. To persist widths across app restarts, save the `columnWidths` map to local storage (using packages like `shared_preferences` or `hive`) in the `onColumnResizeUpdate` callback, and restore the values when the widget initializes. - -**Columns not resizing visually?** -Ensure that `onColumnResizeUpdate` returns `true` and that `columnWidths` map is properly updated in `setState()`. Also verify that the column width is not set to a fixed value that overrides the resized width. - -**Resizing feels sluggish?** -Use `columnResizeMode: ColumnResizeMode.onResizeEnd` instead of the default `onResize` mode to reduce callback frequency and improve performance. - ## Customize indicator appearance The column resizing indicator color and its width can be customized by using the [SfDataGridThemeData.columnResizeIndicatorColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnResizeIndicatorColor.html) and [SfDataGridThemeData.columnResizeIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnResizeIndicatorStrokeWidth.html) properties. ->**Note** ->The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. Ensure this package is added to your project dependencies. +> **Note:** The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. Ensure this package is added to your project dependencies. Import the following file: diff --git a/Flutter/datagrid/footer.md b/Flutter/datagrid/footer.md index 7ee8b799d..abc145d88 100644 --- a/Flutter/datagrid/footer.md +++ b/Flutter/datagrid/footer.md @@ -11,7 +11,7 @@ documentation: ug The footer row is an additional row that displays below the last data row in the grid. Widgets can be displayed in the footer row by setting the [SfDataGrid.footer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footer.html) property. -> **NOTE:** Before implementing the footer functionality, ensure you have set up the SfDataGrid with a valid [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) and configured the necessary columns. +> **Note:** Before implementing the footer functionality, ensure you have set up the SfDataGrid with a valid [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) and configured the necessary columns. {% tabs %} {% highlight Dart %} @@ -192,60 +192,6 @@ By default, the footer row is displayed below the last data row. To keep the foo ![flutter datagrid shows footer always on bottom](images/footer/flutter-datagrid-footer-on-bottom.gif) -## Updating footer content dynamically - -The footer content can be updated dynamically by rebuilding the widget when the data changes. Use a [StreamBuilder](https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html) or [ValueListenableBuilder](https://api.flutter.dev/flutter/foundation/ValueListenableBuilder-class.html) to reactively update the footer display based on data changes. - -{% tabs %} -{% highlight Dart %} - - @override - Widget build(BuildContext context) { - return SfDataGrid( - source: _employeeDataSource, - footer: StreamBuilder( - stream: _employeeDataSource.rowCountStream, - builder: (context, snapshot) { - return Container( - color: Colors.grey[400], - child: Padding( - padding: EdgeInsets.all(8.0), - child: Text( - 'Total Employees: ${snapshot.data ?? 0}', - style: TextStyle(fontWeight: FontWeight.bold), - ))); - }), - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Designation'))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ]); - } - -{% endhighlight %} -{% endtabs %} - ## API reference Refer to the following API documentation for footer-related properties: @@ -254,8 +200,3 @@ Refer to the following API documentation for footer-related properties: * [SfDataGrid.footerHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerHeight.html) — Sets the height of the footer row. Default value is 49.0. * [SfDataGrid.footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) — Sets the number of frozen footer rows. Set to 1 to keep the footer visible during vertical scrolling. * [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — Base class for providing rows to SfDataGrid. - -## See also - -* [Header in Flutter DataGrid](https://help.syncfusion.com/flutter/datagrid/header) -* [Frozen rows and columns in Flutter DataGrid](https://help.syncfusion.com/flutter/datagrid/frozen-pane) diff --git a/Flutter/datagrid/freeze-panes.md b/Flutter/datagrid/freeze-panes.md index 7c97b8a38..a0f82bf0f 100644 --- a/Flutter/datagrid/freeze-panes.md +++ b/Flutter/datagrid/freeze-panes.md @@ -11,8 +11,6 @@ documentation: ug The rows and columns can freeze in view like in Excel. They can be frozen by setting the following properties. -N> Before implementing freeze panes, ensure you have added the `syncfusion_flutter_datagrid` package to your project and created a `DataGridSource` for your data. For more details, refer to [DataGrid Getting Started](getting-started.md). -
@@ -85,8 +83,8 @@ The following code example shows how to freeze a column at left using `frozenCol {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { @@ -181,8 +179,8 @@ The following code example shows how to freeze a column at right using the `foot {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { @@ -286,8 +284,8 @@ The following code example shows how to freeze a row at the top using the `froze {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { @@ -381,8 +379,8 @@ The following code example shows how to freeze a row at the bottom using the `fo {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { @@ -477,7 +475,7 @@ import 'package:flutter/material.dart'; * SfDataGrid has support to freeze the number of rows from top or bottom. There is no support to freeze a specific row. -N> Header row is frozen by default and works regardless of the `frozenRowsCount` property. +> **Note:** Header row is frozen by default and works regardless of the `frozenRowsCount` property. ## Appearance @@ -488,8 +486,8 @@ The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the [sy {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; {% endhighlight %} {% endtabs %} @@ -505,12 +503,13 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Scaffold( - body: SfDataGridTheme( - data: SfDataGridThemeData( + body: SfDataGridTheme( + data: SfDataGridThemeData( frozenPaneElevation: 0.0, frozenPaneLineColor: Colors.red, - frozenPaneLineWidth: 1.5), - child: SfDataGrid( + frozenPaneLineWidth: 1.5, + ), + child: SfDataGrid( source: _orderDataGridSource, frozenRowsCount: 1, footerFrozenRowsCount: 1, @@ -518,79 +517,73 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; footerFrozenColumnsCount: 1, columns: [ GridColumn( - columnName: 'id', - label: Container( - alignment: Alignment.centerRight, - padding: EdgeInsets.symmetric(horizontal: 16.0), - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + alignment: Alignment.centerRight, + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'productId', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Product ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'productId', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Product ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Customer Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Customer Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'product', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Product', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'product', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Product', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'orderDate', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Order Date', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'orderDate', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text('Order Date', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'quantity', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Quantity', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'quantity', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Quantity', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'city', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'City', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'city', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('City', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'unitPrice', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Unit Price', - overflow: TextOverflow.ellipsis, - ))) - ]), - )); + columnName: 'unitPrice', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Unit Price', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ), + ); } {% endhighlight %} @@ -703,9 +696,9 @@ By default, the elevation effect is applied to frozen panes. To hide the elevati {% tabs %} {% highlight Dart %} +import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_core/theme.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -import 'package:flutter/material.dart'; @override Widget build(BuildContext context) { @@ -801,8 +794,7 @@ import 'package:flutter/material.dart'; ![flutter datagrid shows how to hide the frozen pane elevation](images/frozen-pane/flutter-datagrid-hide-frozen-elevation.png) -N> **Header row behavior** — The header row is frozen by default and remains frozen regardless of the `frozenRowsCount` property. This ensures the column headers remain visible while scrolling through data. - -N> **Interaction with other features** — Frozen panes work seamlessly with other DataGrid features including sorting, filtering, selection, and styling. Frozen rows and columns maintain their visual separation during these operations. - -N> **Sample applications** — Refer to the [DataGrid freeze panes sample](https://github.com/syncfusion/flutter-examples/blob/master/lib/samples/datagrid/datagrid_freezepanes.dart) in the Syncfusion Flutter Examples repository for a complete working implementation. +> **Note:** +>- **Header row behavior** — The header row is frozen by default and remains frozen regardless of the `frozenRowsCount` property. This ensures the column headers remain visible while scrolling through data. +>- **Interaction with other features** — Frozen panes work seamlessly with other DataGrid features including sorting, filtering, selection, and styling. Frozen rows and columns maintain their visual separation during these operations. +>- **Sample applications** — Refer to the [DataGrid freeze panes sample](https://support.syncfusion.com/kb/article/10748/how-to-add-fixed-header-freeze-panes-in-flutter-datatable-sfdatagrid) in the Syncfusion Flutter Examples repository for a complete working implementation. diff --git a/Flutter/datagrid/load-more.md b/Flutter/datagrid/load-more.md index 965809332..400283a6d 100644 --- a/Flutter/datagrid/load-more.md +++ b/Flutter/datagrid/load-more.md @@ -13,9 +13,6 @@ The SfDataGrid widget provides support to display an interactive view when the g To implement load more functionality, override the [DataGridSource.handleLoadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleLoadMoreRows.html) method to load additional rows and notify the grid about the changes. The `handleLoadMoreRows` method is automatically called when the user scrolls to the bottom of the grid. Use the [LoadMoreRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/LoadMoreRows.html) function, passed as a parameter to `loadMoreViewBuilder`, to trigger row loading. -**NOTE** -Requires `syncfusion_flutter_datagrid` package. Refer to the [getting started](https://help.syncfusion.com/flutter/datagrid/getting-started) guide for setup instructions. - ## Infinite scrolling Infinite scrolling automatically loads more rows as the user scrolls to the bottom of the grid, creating a seamless continuous data experience. This approach is ideal when you have a large dataset and want to load data progressively without user interaction. @@ -31,43 +28,27 @@ import 'dart:math'; class Employee { Employee(this.id, this.name, this.designation, this.salary); + final int id; final String name; final String designation; final int salary; } -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return const MaterialApp(home: Home()); - } -} - -class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - @override - State createState() => _HomeState(); -} - -class _HomeState extends State { +class MyHomePageState extends State { + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Load More - Infinite Scrolling')), body: SfDataGrid( source: _employeeDataSource, loadMoreViewBuilder: (BuildContext context, LoadMoreRows loadMoreRows) { @@ -80,86 +61,92 @@ class _HomeState extends State { } return FutureBuilder( - initialData: 'loading', - future: loadRows(), - builder: (context, snapShot) { - if (snapShot.data == 'loading') { - return Container( - height: 60.0, - width: double.infinity, - decoration: BoxDecoration( - color: Colors.white, - border: BorderDirectional( - top: BorderSide( - width: 1.0, - color: Color.fromRGBO(0, 0, 0, 0.26)))), - alignment: Alignment.center, - child: CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(Colors.deepPurple))); - } else { - return SizedBox.fromSize(size: Size.zero); - } - }); + initialData: 'loading', + future: loadRows(), + builder: (context, snapShot) { + if (snapShot.data == 'loading') { + return Container( + height: 60.0, + width: double.infinity, + decoration: BoxDecoration( + color: Colors.white, + border: BorderDirectional( + top: BorderSide( + width: 1.0, + color: Color.fromRGBO(0, 0, 0, 0.26), + ), + ), + ), + alignment: Alignment.center, + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(Colors.deepPurple), + ), + ); + } else { + return SizedBox.fromSize(size: Size.zero); + } + }, + ); }, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ]), - ); + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } } -class EmployeeDataSource extends DataGridSource { - static final List _employees = [ - Employee(1001, 'James', 'Project Lead', 20000), - Employee(1002, 'Kathryn', 'Manager', 30000), - Employee(1003, 'Lara', 'Developer', 15000), - Employee(1004, 'Michael', 'Designer', 15000), - Employee(1005, 'Andrew', 'Developer', 15000), - Employee(1006, 'Gail', 'Manager', 25000), - Employee(1007, 'Nancy', 'CEO', 50000), - Employee(1008, 'Margaret', 'Developer', 15000), - Employee(1009, 'Steven', 'Developer', 15000), - Employee(1010, 'Michael', 'System Analyst', 20000), - Employee(1011, 'Robert', 'Developer', 15000), - Employee(1012, 'Laura', 'Developer', 15000), +List getEmployeeData() { + return [ + Employee(10001, 'James', 'Project Lead', 20000), + Employee(10002, 'Kathryn', 'Manager', 30000), + Employee(10003, 'Lara', 'Developer', 15000), + Employee(10004, 'Michael', 'Designer', 15000), + Employee(10005, 'Martin', 'Developer', 15000), + Employee(10006, 'Newberry', 'Developer', 15000), + Employee(10007, 'Balnc', 'Developer', 15000), + Employee(10008, 'Perry', 'Developer', 15000), + Employee(10009, 'Gable', 'Developer', 15000), + Employee(10010, 'Grimes', 'Developer', 15000), ]; +} + +class EmployeeDataSource extends DataGridSource { + static final List _employees = []; - EmployeeDataSource() { + EmployeeDataSource({required List employeeData}) { + _employees.addAll(employeeData); buildDataGridRows(); } @@ -171,9 +158,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -181,8 +169,10 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } @override @@ -196,14 +186,22 @@ class EmployeeDataSource extends DataGridSource { void buildDataGridRows() { dataGridRows = _employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), + columnName: 'designation', + value: dataGridRow.designation, + ), DataGridCell( - columnName: 'salary', value: dataGridRow.salary), - ])) + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -212,12 +210,14 @@ class EmployeeDataSource extends DataGridSource { final startIndex = employees.isNotEmpty ? employees.length : 0, endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { - employees.add(Employee( - 1000 + i, - _names[random.nextInt(_names.length)], - _designation[random.nextInt(_designation.length)], - 10000 + random.nextInt(10000), - )); + employees.add( + Employee( + 1000 + i, + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), + ), + ); } } @@ -236,7 +236,7 @@ class EmployeeDataSource extends DataGridSource { 'Riscu', 'Seves', 'Vaffe', - 'Alfki' + 'Alfki', ]; final List _designation = [ @@ -245,15 +245,14 @@ class EmployeeDataSource extends DataGridSource { 'Manager', 'Designer', 'System Analyst', - 'CEO' + 'CEO', ]; } {% endhighlight %} {% endtabs %} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-do-the-infinite-scrolling-in-syncfusion-flutter-datatable). +> **Note:** Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-do-the-infinite-scrolling-in-syncfusion-flutter-datatable). ![flutter datagrid shows load more with infinite scrolling behavior](images/load-more/flutter-datagrid-load-more-infinite-scrolling.gif) @@ -272,162 +271,162 @@ import 'dart:math'; class Employee { Employee(this.id, this.name, this.designation, this.salary); + final int id; final String name; final String designation; final int salary; } -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - @override - Widget build(BuildContext context) { - return const MaterialApp(home: Home()); - } -} - -class Home extends StatefulWidget { - const Home({Key? key}) : super(key: key); - @override - State createState() => _HomeState(); -} - -class _HomeState extends State { +class MyHomePageState extends State { + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: const Text('Load More - Button')), body: SfDataGrid( source: _employeeDataSource, loadMoreViewBuilder: (BuildContext context, LoadMoreRows loadMoreRows) { bool showIndicator = false; return StatefulBuilder( - builder: (BuildContext context, StateSetter setState) { - if (showIndicator) { - return Container( + builder: (BuildContext context, StateSetter setState) { + if (showIndicator) { + return Container( height: 60.0, width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( - color: Colors.white, - border: const BorderDirectional( - top: BorderSide( - width: 1.0, color: Color.fromRGBO(0, 0, 0, 0.26)))), + color: Colors.white, + border: const BorderDirectional( + top: BorderSide( + width: 1.0, + color: Color.fromRGBO(0, 0, 0, 0.26), + ), + ), + ), child: const CircularProgressIndicator( - valueColor: AlwaysStoppedAnimation(Colors.deepPurple))); - } else { - return Container( + valueColor: AlwaysStoppedAnimation(Colors.deepPurple), + ), + ); + } else { + return Container( height: 60.0, width: double.infinity, alignment: Alignment.center, decoration: BoxDecoration( - color: Colors.white, - border: const BorderDirectional( - top: BorderSide( - width: 1.0, color: Color.fromRGBO(0, 0, 0, 0.26)))), + color: Colors.white, + border: const BorderDirectional( + top: BorderSide( + width: 1.0, + color: Color.fromRGBO(0, 0, 0, 0.26), + ), + ), + ), child: SizedBox( - height: 36.0, - width: 142.0, - child: TextButton( - style: ButtonStyle( - backgroundColor: - MaterialStateProperty.all(Colors.purple)), - child: const Text('LOAD MORE', - style: TextStyle(color: Colors.white)), - onPressed: () async { - // Check if the widget is still mounted to avoid - // "setState() called after dispose()" errors - if (context is StatefulElement && - context.state.mounted) { - setState(() { - showIndicator = true; - }); - } - // Call the loadMoreRows function to trigger - // DataGridSource.handleLoadMoreRows method - await loadMoreRows(); - // Reset the indicator state when loading completes - if (context is StatefulElement && - context.state.mounted) { - setState(() { - showIndicator = false; - }); - } - }))); - } - }); + height: 36.0, + width: 142.0, + child: TextButton( + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.purple), + ), + child: const Text( + 'LOAD MORE', + style: TextStyle(color: Colors.white), + ), + onPressed: () async { + // Check if the widget is still mounted to avoid + // "setState() called after dispose()" errors + if (context is StatefulElement && + context.state.mounted) { + setState(() { + showIndicator = true; + }); + } + // Call the loadMoreRows function to trigger + // DataGridSource.handleLoadMoreRows method + await loadMoreRows(); + // Reset the indicator state when loading completes + if (context is StatefulElement && + context.state.mounted) { + setState(() { + showIndicator = false; + }); + } + }, + ), + ), + ); + } + }, + ); }, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))) - ]), - ); + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ); } } -class EmployeeDataSource extends DataGridSource { - static final List _employees = [ - Employee(1001, 'James', 'Project Lead', 20000), - Employee(1002, 'Kathryn', 'Manager', 30000), - Employee(1003, 'Lara', 'Developer', 15000), - Employee(1004, 'Michael', 'Designer', 15000), - Employee(1005, 'Andrew', 'Developer', 15000), - Employee(1006, 'Gail', 'Manager', 25000), - Employee(1007, 'Nancy', 'CEO', 50000), - Employee(1008, 'Margaret', 'Developer', 15000), - Employee(1009, 'Steven', 'Developer', 15000), - Employee(1010, 'Michael', 'System Analyst', 20000), - Employee(1011, 'Robert', 'Developer', 15000), - Employee(1012, 'Laura', 'Developer', 15000), +List getEmployeeData() { + return [ + Employee(10001, 'James', 'Project Lead', 20000), + Employee(10002, 'Kathryn', 'Manager', 30000), + Employee(10003, 'Lara', 'Developer', 15000), + Employee(10004, 'Michael', 'Designer', 15000), + Employee(10005, 'Martin', 'Developer', 15000), + Employee(10006, 'Newberry', 'Developer', 15000), + Employee(10007, 'Balnc', 'Developer', 15000), + Employee(10008, 'Perry', 'Developer', 15000), + Employee(10009, 'Gable', 'Developer', 15000), + Employee(10010, 'Grimes', 'Developer', 15000), ]; +} + +class EmployeeDataSource extends DataGridSource { + static final List _employees = []; - EmployeeDataSource() { + EmployeeDataSource({required List employeeData}) { + _employees.addAll(employeeData); buildDataGridRows(); } @@ -439,9 +438,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -449,8 +449,10 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } @override @@ -464,14 +466,22 @@ class EmployeeDataSource extends DataGridSource { void buildDataGridRows() { dataGridRows = _employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), + columnName: 'designation', + value: dataGridRow.designation, + ), DataGridCell( - columnName: 'salary', value: dataGridRow.salary), - ])) + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -480,12 +490,14 @@ class EmployeeDataSource extends DataGridSource { final startIndex = employees.isNotEmpty ? employees.length : 0, endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { - employees.add(Employee( - 1000 + i, - _names[random.nextInt(_names.length)], - _designation[random.nextInt(_designation.length)], - 10000 + random.nextInt(10000), - )); + employees.add( + Employee( + 1000 + i, + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), + ), + ); } } @@ -504,7 +516,7 @@ class EmployeeDataSource extends DataGridSource { 'Riscu', 'Seves', 'Vaffe', - 'Alfki' + 'Alfki', ]; final List _designation = [ @@ -513,15 +525,14 @@ class EmployeeDataSource extends DataGridSource { 'Manager', 'Designer', 'System Analyst', - 'CEO' + 'CEO', ]; } {% endhighlight %} {% endtabs %} -**NOTE** - Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-rows-on-demand-in-Syncfusion-Flutter-datatable). +> **Note:** Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-rows-on-demand-in-Syncfusion-Flutter-datatable). ![flutter datagrid shows load more button behavior](images/load-more/flutter-datagrid-load-more-button.gif) @@ -547,6 +558,3 @@ class EmployeeDataSource extends DataGridSource { ``` - **Error handling**: Implement proper error handling in your load more logic to gracefully handle network failures and retry options. - -**NOTE** -Refer to the [DataGridSource API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) for more information about load more row handling. diff --git a/Flutter/datagrid/placeholder.md b/Flutter/datagrid/placeholder.md index 9ff7b3fea..b0c26daaa 100644 --- a/Flutter/datagrid/placeholder.md +++ b/Flutter/datagrid/placeholder.md @@ -11,8 +11,6 @@ documentation: ug The `SfDataGrid` provides built-in support for displaying a placeholder when the data source is empty by setting the [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) property. The `placeholder` property accepts a `Widget` that will be displayed in the scroll view area when the DataGrid has no data to show. -N> **Note:** Ensure you have implemented a [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) class and configured [GridColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/GridColumn-class.html) objects before implementing the placeholder feature. For detailed setup instructions, refer to the [Getting Started with SfDataGrid](getting-started.md) documentation. - The following example shows how to add a `placeholder` in SfDataGrid: {% tabs %} @@ -101,10 +99,4 @@ The placeholder is automatically hidden when: * [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) — Gets or sets the widget to display when the DataGrid is empty. * [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — The data source for populating the DataGrid. -**See Also** - -* [Getting Started with SfDataGrid](getting-started.md) -* [Styling DataGrid Cells](styles.md) -* [DataGrid Column Types](column-types.md) - -N> **Sample applications** — Refer to the [DataGrid placeholder sample](https://github.com/SyncfusionExamples/getting-started-with-flutter-datagrid) in the Syncfusion Flutter Examples repository for a complete working implementation. +> **Sample application:** — Refer to the [DataGrid placeholder sample](https://support.syncfusion.com/kb/article/19825/how-to-show-an-empty-message-in-flutter-datatable) in the Syncfusion Flutter Examples repository for a complete working implementation. diff --git a/Flutter/datagrid/pull-to-refresh.md b/Flutter/datagrid/pull-to-refresh.md index e6de30aec..c9ed31c08 100644 --- a/Flutter/datagrid/pull-to-refresh.md +++ b/Flutter/datagrid/pull-to-refresh.md @@ -11,8 +11,6 @@ documentation: ug The SfDataGrid provides support to add more data at runtime by using the pull-to-refresh feature. You can enable the pull-to-refresh option by setting the [SfDataGrid.allowPullToRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowPullToRefresh.html) property to `true` and overriding the [DataGridSource.handleRefresh](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handleRefresh.html) method to add new data to the data source at runtime, then notify the data grid about the changes. -> **Note:** This feature requires the `syncfusion_flutter_datagrid` package. Ensure you have added it to your `pubspec.yaml` file. Pull-to-refresh is supported on Flutter 2.0 and above. - {% tabs %} {% highlight Dart %} @@ -21,99 +19,93 @@ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class Employee { + Employee(this.id, this.name, this.designation, this.salary); + final int id; final String name; final String designation; final int salary; - - Employee( - this.id, - this.name, - this.designation, - this.salary, - ); -} - -class PullToRefreshDemo extends StatefulWidget { - @override - State createState() => _PullToRefreshDemoState(); } -class _PullToRefreshDemoState extends State { +class PullToRefreshDemoState extends State { + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { - return SfDataGrid( - allowPullToRefresh: true, - source: _employeeDataSource, - columns: [ - GridColumn( + return Scaffold( + body: SfDataGrid( + allowPullToRefresh: true, + source: _employeeDataSource, + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), ); } } +List getEmployeeData() { + return [ + Employee(10001, 'James', 'Project Lead', 20000), + Employee(10002, 'Kathryn', 'Manager', 30000), + Employee(10003, 'Lara', 'Developer', 15000), + Employee(10004, 'Michael', 'Designer', 15000), + Employee(10005, 'Martin', 'Developer', 15000), + Employee(10006, 'Newberry', 'Developer', 15000), + Employee(10007, 'Balnc', 'Developer', 15000), + Employee(10008, 'Perry', 'Developer', 15000), + Employee(10009, 'Gable', 'Developer', 15000), + Employee(10010, 'Grimes', 'Developer', 15000), + ]; +} + class EmployeeDataSource extends DataGridSource { late List _employees = []; - EmployeeDataSource() { - _initializeEmployees(); + EmployeeDataSource({required List employeeData}) { + _employees = employeeData; buildDataGridRows(); } - void _initializeEmployees() { - _employees = [ - Employee(1001, 'Welli', 'Project Lead', 20000), - Employee(1002, 'Blonp', 'Developer', 18000), - Employee(1003, 'Folko', 'Manager', 22000), - Employee(1004, 'Furip', 'Designer', 17000), - Employee(1005, 'Folig', 'System Analyst', 19000), - Employee(1006, 'Picco', 'CEO', 30000), - ]; - } - List dataGridRows = []; @override @@ -122,9 +114,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -132,8 +125,10 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } @override @@ -147,14 +142,22 @@ class EmployeeDataSource extends DataGridSource { void buildDataGridRows() { dataGridRows = _employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), + columnName: 'designation', + value: dataGridRow.designation, + ), DataGridCell( - columnName: 'salary', value: dataGridRow.salary), - ])) + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -163,12 +166,14 @@ class EmployeeDataSource extends DataGridSource { final startIndex = employees.isNotEmpty ? employees.length : 0; final endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { - employees.add(Employee( - 1000 + i, - _names[random.nextInt(_names.length)], - _designation[random.nextInt(_designation.length)], - 10000 + random.nextInt(10000), - )); + employees.add( + Employee( + 1000 + i, + _names[random.nextInt(_names.length)], + _designation[random.nextInt(_designation.length)], + 10000 + random.nextInt(10000), + ), + ); } } @@ -187,7 +192,7 @@ class EmployeeDataSource extends DataGridSource { 'Riscu', 'Seves', 'Vaffe', - 'Alfki' + 'Alfki', ]; final List _designation = [ @@ -196,14 +201,14 @@ class EmployeeDataSource extends DataGridSource { 'Manager', 'Designer', 'System Analyst', - 'CEO' + 'CEO', ]; } {% endhighlight %} {% endtabs %} -Download the demo application from [GitHub](https://github.com/SyncfusionExamples/pull-to-refresh-support-in-flutter-datatable-sfdatagrid). +> **Reference:** Download the demo application from [GitHub](https://github.com/SyncfusionExamples/pull-to-refresh-support-in-flutter-datatable-sfdatagrid). ![flutter datagrid shows default view of refresh indicator](images/pull-to-refresh/flutter-datagrid-pull-to-refresh.gif) @@ -221,79 +226,76 @@ To set the indicator's color and background color, use the [ColorScheme](https:/ import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -class CustomRefreshIndicatorDemo extends StatefulWidget { - @override - State createState() => _CustomRefreshIndicatorDemoState(); -} - -class _CustomRefreshIndicatorDemoState extends State { +class CustomRefreshIndicatorDemoState + extends State { + List _employees = []; late EmployeeDataSource _employeeDataSource; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); } @override Widget build(BuildContext context) { - return Theme( + return Scaffold( + body: Theme( data: ThemeData( - brightness: Brightness.light, - scaffoldBackgroundColor: Colors.white, - colorScheme: const ColorScheme.light( - primary: Colors.blue, - surface: Colors.lightBlue)), + brightness: Brightness.light, + canvasColor: Colors.lightBlue, + colorScheme: const ColorScheme.light(primary: Colors.white), + ), child: SfDataGrid( - allowPullToRefresh: true, - source: _employeeDataSource, - refreshIndicatorStrokeWidth: 3.0, - refreshIndicatorDisplacement: 60.0, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ])); + allowPullToRefresh: true, + source: _employeeDataSource, + refreshIndicatorStrokeWidth: 3.0, + refreshIndicatorDisplacement: 60.0, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ), + ); } } {% endhighlight %} {% endtabs %} -Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-customize-the-refresh-indicator-appearance-in-flutter-datatable-sfdatagrid). +> **Reference:** Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-customize-the-refresh-indicator-appearance-in-flutter-datatable-sfdatagrid). ![flutter datagrid shows customized refresh indicator](images/pull-to-refresh/flutter-datagrid-customized-pull-to-refresh-indicator.gif) @@ -308,112 +310,179 @@ The `refresh()` method calls the [DataGridSource.handleRefresh()](https://pub.de {% tabs %} {% highlight Dart %} +import 'dart:math'; import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -class ProgrammaticRefreshDemo extends StatefulWidget { - @override - State createState() => _ProgrammaticRefreshDemoState(); -} - -class _ProgrammaticRefreshDemoState extends State { - late EmployeeDataSource _employeeDataSource; - final GlobalKey _dataGridKey = GlobalKey(); +EmployeeDataSource _employeeDataSource = EmployeeDataSource(); +List _employees = []; +final GlobalKey key = GlobalKey(); +class PullToRefreshSampleState extends State { @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(); + _employees = getEmployeeData(); } - Future _onRefreshPressed() async { - try { - // Refresh with indicator - await _dataGridKey.currentState!.refresh(); - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error refreshing data: $e')), - ); - } + @override + Widget build(BuildContext context) { + return Scaffold( + body: SfDataGrid( + key: key, + allowPullToRefresh: true, + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: const Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: const Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: const Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: const Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + floatingActionButton: FloatingActionButton( + child: const Icon(Icons.refresh), + onPressed: () { + key.currentState!.refresh(); + }, + ), + ); } +} - Future _onSilentRefreshPressed() async { - try { - // Refresh without showing indicator - await _dataGridKey.currentState!.refresh(showRefreshIndicator: false); - } catch (e) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar(content: Text('Error refreshing data: $e')), - ); - } +class EmployeeDataSource extends DataGridSource { + EmployeeDataSource() { + buildDataGridRows(); } + List dataGridRows = []; + @override - Widget build(BuildContext context) { - return Scaffold( - body: SfDataGrid( - key: _dataGridKey, - allowPullToRefresh: true, - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + List get rows => dataGridRows; + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || + dataGridCell.columnName == 'salary') + ? Alignment.centerRight + : Alignment.centerLeft, + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Text( + dataGridCell.value.toString(), + overflow: TextOverflow.ellipsis, + ), + ); + }).toList(), + ); + } + + @override + Future handleRefresh() async { + await Future.delayed(const Duration(seconds: 5)); + _addMoreRows(_employees, 15); + buildDataGridRows(); + notifyListeners(); + } + + void buildDataGridRows() { + dataGridRows = _employees + .map( + (dataGridRow) => DataGridRow( + cells: [ + DataGridCell(columnName: 'id', value: dataGridRow.id), + DataGridCell(columnName: 'name', value: dataGridRow.name), + DataGridCell( columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + value: dataGridRow.designation, + ), + DataGridCell( columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], + value: dataGridRow.salary, + ), + ], + ), + ) + .toList(); + } + + void _addMoreRows(List employees, int count) { + final Random random = Random(); + final startIndex = employees.isNotEmpty ? employees.length : 0, + endIndex = startIndex + count; + for (int i = startIndex; i < endIndex; i++) { + employees.add( + Employee( + 1000 + i, + _names[random.nextInt(_names.length - 1)], + _designation[random.nextInt(_designation.length - 1)], + 10000 + random.nextInt(10000), ), - floatingActionButton: Column( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - FloatingActionButton( - heroTag: 'refresh_with_indicator', - child: Icon(Icons.refresh), - onPressed: _onRefreshPressed), - SizedBox(height: 10), - FloatingActionButton( - heroTag: 'refresh_without_indicator', - child: Icon(Icons.cloud_download), - onPressed: _onSilentRefreshPressed), - ], - )); + ); + } } + + final List _names = [ + 'Welli', + 'Blonp', + 'Folko', + 'Furip', + 'Folig', + 'Picco', + 'Frans', + 'Warth', + 'Linod', + 'Simop', + 'Merep', + 'Riscu', + 'Seves', + 'Vaffe', + 'Alfki', + ]; + + final List _designation = [ + 'Project Lead', + 'Developer', + 'Manager', + 'Designer', + 'System Analyst', + 'CEO', + ]; } {% endhighlight %} {% endtabs %} -Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-pull-to-refresh-programmatically-in-flutter-datatable-sfdatagrid). +> **Reference:** Download the demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-pull-to-refresh-programmatically-in-flutter-datatable-sfdatagrid). ![flutter datagrid shows programmatic refresh indicator](images/pull-to-refresh/flutter-datagrid-programmatic-pull-to-refresh.gif) diff --git a/Flutter/datagrid/styles.md b/Flutter/datagrid/styles.md index ee99e95d9..10f73cf77 100644 --- a/Flutter/datagrid/styles.md +++ b/Flutter/datagrid/styles.md @@ -13,7 +13,7 @@ The DataGrid supports changing the appearance of the grid by using the [SfDataGr The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package. So, import the below file, -N> The `SfDataGridTheme` is optional. If not provided, the DataGrid uses default styling values. +> **Note:** The `SfDataGridTheme` is optional. If not provided, the DataGrid uses default styling values. {% tabs %} {% highlight Dart %} @@ -27,7 +27,7 @@ import 'package:syncfusion_flutter_core/theme.dart'; Change the header background color by using [SfDataGridThemeData.headerColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/headerColor.html) property. The default header background color is based on the platform's theme (light or dark). -N> This property applies to all column headers in the grid. +> **Note:** This property applies to all column headers in the grid. {% tabs %} {% highlight Dart %} @@ -85,7 +85,7 @@ N> This property applies to all column headers in the grid. Change the color of the header on hovering by using the [headerHoverColor]( https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/headerHoverColor.html) property. -N> This is applicable for web and desktop platforms. +> **Note:** This is applicable for web and desktop platforms. {% tabs %} {% highlight Dart %} @@ -143,7 +143,7 @@ N> This is applicable for web and desktop platforms. The DataGrid supports changing the row background color by using [DataGridRowAdapter.color](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridRowAdapter/color.html) property. -N> You must implement a custom [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) and override the [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) method to apply row background colors. +> **Note:** You must implement a custom [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) and override the [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) method to apply row background colors. {% tabs %} {% highlight Dart %} @@ -198,7 +198,7 @@ class EmployeeDataSource extends DataGridSource { The color and thickness of the grid lines can be changed by using the [SfDataGridThemeData.gridLineColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/gridLineColor.html) and [SfDataGridThemeData.gridLineStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/gridLineStrokeWidth.html) properties. -N> Default `gridLineColor` is based on the platform theme. Default `gridLineStrokeWidth` is 1.0. Both properties apply to grid lines controlled by `gridLinesVisibility` and `headerGridLinesVisibility` properties. +> **Note:** Default `gridLineColor` is based on the platform theme. Default `gridLineStrokeWidth` is 1.0. Both properties apply to grid lines controlled by `gridLinesVisibility` and `headerGridLinesVisibility` properties. {% tabs %} {% highlight Dart %} @@ -330,7 +330,7 @@ The following code describes how to show vertical and horizontal grid lines for By default, the row highlighting on hovering support is enabled for the web and desktop platforms. Disable the row highlighting by setting the [SfDataGrid.highlightRowOnHover](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/highlightRowOnHover.html) property to `false`. -N> Row highlighting on hover is only applicable for web and desktop platforms. On mobile platforms (iOS, Android), row highlighting is not shown. +> **Note:** Row highlighting on hover is only applicable for web and desktop platforms. On mobile platforms (iOS, Android), row highlighting is not shown. {% tabs %} {% highlight Dart %} @@ -380,7 +380,7 @@ N> Row highlighting on hover is only applicable for web and desktop platforms. O Change the row highlighting color and text style by using the [SfDataGridThemeData.rowHoverColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/rowHoverColor.html) and the [SfDataGridThemeData.rowHoverTextStyle](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/rowHoverTextStyle.html) properties. -N> Both properties work together to customize the hover appearance. Setting only `rowHoverColor` applies the background color while keeping the default text style. Setting only `rowHoverTextStyle` applies the text styling while keeping the default hover background. These properties are applicable for web and desktop platforms only. +> **Note:** Both properties work together to customize the hover appearance. Setting only `rowHoverColor` applies the background color while keeping the default text style. Setting only `rowHoverTextStyle` applies the text styling while keeping the default hover background. These properties are applicable for web and desktop platforms only. {% tabs %} {% highlight Dart %} @@ -436,7 +436,7 @@ N> Both properties work together to customize the hover appearance. Setting only The DataGrid requires a widget for each cell from the user end. Typically, users load the [Text](https://api.flutter.dev/flutter/widgets/Text-class.html) widget to display the cell values. Text color can be changed by setting the [TextStyle](https://api.flutter.dev/flutter/painting/TextStyle-class.html) to the style property of the `Text` widget. -N> Cell customization requires overriding the [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) method in [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html). This is the recommended approach for per-cell styling. +> **Note:** Cell customization requires overriding the [buildRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/buildRow.html) method in [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html). This is the recommended approach for per-cell styling. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/swiping.md b/Flutter/datagrid/swiping.md index 0514b4b18..4bed79988 100644 --- a/Flutter/datagrid/swiping.md +++ b/Flutter/datagrid/swiping.md @@ -11,8 +11,6 @@ documentation: ug The Flutter DataTable provides support to swipe a row by setting the [SfDataGrid.allowSwiping](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/allowSwiping.html) property to true. Swipe actions will be displayed when swiping a row from `left to right` or `right to left` direction. The swipe dragging gesture can be restricted to a certain point on the row by setting the [SfDataGrid.swipeMaxOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/swipeMaxOffset.html) property. -> **Note:** Ensure the `syncfusion_flutter_datagrid` package is installed and imported in your project. - ## Swipe action builders The Flutter DataTable enables you to load the desired widget behind the swiped row by using [SfDataGrid.startSwipeActionsBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/startSwipeActionsBuilder.html) and [SfDataGrid.endSwipeActionsBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/endSwipeActionsBuilder.html) properties. The swipe widget's width that loads from the actions builder is arranged based on the `SfDataGrid.swipeMaxOffset` property and it takes height based on the current swiping row height. @@ -23,12 +21,7 @@ The following code demonstrates how to implement swipe actions: ```dart class Employee { - Employee({ - required this.id, - required this.name, - required this.designation, - required this.salary, - }); + Employee(this.id, this.name, this.designation, this.salary); final int id; final String name; @@ -38,12 +31,18 @@ class Employee { List getEmployeeData() { return [ - Employee(id: 1001, name: 'James', designation: 'Developer', salary: 15000), - Employee(id: 1002, name: 'Kathryn', designation: 'Manager', salary: 25000), - Employee(id: 1003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 1004, name: 'Michael', designation: 'Manager', salary: 25000), + Employee(10001, 'James', 'Project Lead', 20000), + Employee(10002, 'Kathryn', 'Manager', 30000), + Employee(10003, 'Lara', 'Developer', 15000), + Employee(10004, 'Michael', 'Designer', 15000), + Employee(10005, 'Martin', 'Developer', 15000), + Employee(10006, 'Newberry', 'Developer', 15000), + Employee(10007, 'Balnc', 'Developer', 15000), + Employee(10008, 'Perry', 'Developer', 15000), + Employee(10009, 'Gable', 'Developer', 15000), + Employee(10010, 'Grimes', 'Developer', 15000), ]; -} +}; ``` **DataSource Class** @@ -99,7 +98,11 @@ class EmployeeDataSource extends DataGridSource { import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +/// The home page of the application which hosts the datagrid. class SfDataGridExample extends StatefulWidget { + /// Creates the home page. + const SfDataGridExample({super.key}); + @override State createState() => _SfDataGridExampleState(); } @@ -117,81 +120,85 @@ class _SfDataGridExampleState extends State { @override Widget build(BuildContext context) { - return SfDataGrid( - allowSwiping: true, - swipeMaxOffset: 100.0, - source: _employeeDataSource, - startSwipeActionsBuilder: - (BuildContext context, DataGridRow row, int rowIndex) { - return GestureDetector( - onTap: () { - _employeeDataSource.dataGridRows.insert( - rowIndex, - DataGridRow(cells: [ - DataGridCell(value: 1011, columnName: 'id'), - DataGridCell(value: 'Tom Bass', columnName: 'name'), - DataGridCell(value: 'Developer', columnName: 'designation'), - DataGridCell(value: 20000, columnName: 'salary') - ])); - _employeeDataSource.updateDataGridSource(); + return Scaffold( + body: SfDataGrid( + allowSwiping: true, + swipeMaxOffset: 100.0, + source: _employeeDataSource, + startSwipeActionsBuilder: + (BuildContext context, DataGridRow row, int rowIndex) { + return GestureDetector( + onTap: () { + _employeeDataSource.dataGridRows.insert( + rowIndex, + DataGridRow( + cells: [ + DataGridCell(value: 1011, columnName: 'id'), + DataGridCell(value: 'Tom Bass', columnName: 'name'), + DataGridCell( + value: 'Developer', + columnName: 'designation', + ), + DataGridCell(value: 20000, columnName: 'salary'), + ], + ), + ); + _employeeDataSource.updateDataGridSource(); + }, + child: Container( + color: Colors.greenAccent, + child: Center(child: Icon(Icons.add)), + ), + ); }, - child: Container( - color: Colors.greenAccent, - child: Center( - child: Icon(Icons.add), - ))); - }, - endSwipeActionsBuilder: - (BuildContext context, DataGridRow row, int rowIndex) { - return GestureDetector( - onTap: () { - _employeeDataSource.dataGridRows.removeAt(rowIndex); - _employeeDataSource.updateDataGridSource(); + endSwipeActionsBuilder: + (BuildContext context, DataGridRow row, int rowIndex) { + return GestureDetector( + onTap: () { + _employeeDataSource.dataGridRows.removeAt(rowIndex); + _employeeDataSource.updateDataGridSource(); + }, + child: Container( + color: Colors.redAccent, + child: Center(child: Icon(Icons.delete)), + ), + ); }, - child: Container( - color: Colors.redAccent, - child: Center( - child: Icon(Icons.delete), - ))); - }, - columns: [ - GridColumn( + columns: [ + GridColumn( columnName: 'id', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'name', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'designation', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( columnName: 'salary', label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), ); } } @@ -227,96 +234,113 @@ You can perform customized swipe functionality using the swiping callbacks. The import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +/// The home page of the application which hosts the datagrid. class SfDataGridSwipeDeleteExample extends StatefulWidget { + /// Creates the home page. + const SfDataGridSwipeDeleteExample({super.key}); + @override - State createState() => _SfDataGridSwipeDeleteExampleState(); + State createState() => + _SfDataGridSwipeDeleteExampleState(); } class _SfDataGridSwipeDeleteExampleState extends State { + List _employees = []; late EmployeeDataSource _employeeDataSource; bool isReachedCenter = false; @override void initState() { super.initState(); - _employeeDataSource = EmployeeDataSource(employees: getEmployeeData()); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employees: _employees); } @override Widget build(BuildContext context) { - return LayoutBuilder(builder: (context, constraints) { - return SfDataGrid( - allowSwiping: true, - swipeMaxOffset: constraints.maxWidth, - source: _employeeDataSource, - startSwipeActionsBuilder: - (BuildContext context, DataGridRow row, int rowIndex) { - return GestureDetector( - onTap: () { - _employeeDataSource.dataGridRows.removeAt(rowIndex); + return Scaffold( + body: LayoutBuilder( + builder: (context, constraints) { + return SfDataGrid( + allowSwiping: true, + columnWidthMode: ColumnWidthMode.fill, + swipeMaxOffset: constraints.maxWidth, + source: _employeeDataSource, + startSwipeActionsBuilder: + (BuildContext context, DataGridRow row, int rowIndex) { + return GestureDetector( + onTap: () { + _employeeDataSource.dataGridRows.removeAt(rowIndex); + _employeeDataSource.updateDataGridSource(); + }, + child: Container( + color: Colors.green, + padding: EdgeInsets.only(left: 30.0), + alignment: Alignment.centerLeft, + child: Text( + 'Delete', + style: TextStyle(color: Colors.white), + ), + ), + ); + }, + onSwipeUpdate: (details) { + setState(() { + isReachedCenter = + (details.swipeOffset >= constraints.maxWidth / 2) + ? true + : false; + }); + return true; + }, + onSwipeEnd: (details) { + if (isReachedCenter && + _employeeDataSource.dataGridRows.isNotEmpty) { + _employeeDataSource.dataGridRows.removeAt(details.rowIndex); _employeeDataSource.updateDataGridSource(); - }, - child: Container( - color: Colors.green, - padding: EdgeInsets.only(left: 30.0), - alignment: Alignment.centerLeft, - child: Text('Delete', style: TextStyle(color: Colors.white)))); - }, - onSwipeUpdate: (details) { - setState(() { - isReachedCenter = - (details.swipeOffset >= constraints.maxWidth / 2) ? true : false; - }); - return true; - }, - onSwipeEnd: (details) { - if (isReachedCenter && _employeeDataSource.dataGridRows.isNotEmpty) { - _employeeDataSource.dataGridRows.removeAt(details.rowIndex); - _employeeDataSource.updateDataGridSource(); - isReachedCenter = false; - } - }, - columns: [ - GridColumn( - columnName: 'id', - label: Container( + isReachedCenter = false; + } + }, + columns: [ + GridColumn( + columnName: 'id', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'name', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - ); - }); + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ); + }, + ), + ); } +} {% endhighlight %} {% endtabs %} @@ -333,9 +357,14 @@ The [swipeMaxOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/l import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +/// The home page of the application which hosts the datagrid. class SfDataGridDifferentSwipeOffsetsExample extends StatefulWidget { + /// Creates the home page. + const SfDataGridDifferentSwipeOffsetsExample({super.key}); + @override - State createState() => _SfDataGridDifferentSwipeOffsetsExampleState(); + State createState() => + _SfDataGridDifferentSwipeOffsetsExampleState(); } class _SfDataGridDifferentSwipeOffsetsExampleState extends State { @@ -344,97 +373,105 @@ class _SfDataGridDifferentSwipeOffsetsExampleState extends State[ - GridColumn( - columnName: 'id', - label: Container( + return Scaffold( + body: LayoutBuilder( + builder: (context, constraints) { + return SfDataGrid( + allowSwiping: true, + source: _employeeDataSource, + onSwipeStart: (details) { + if (details.swipeDirection == + DataGridRowSwipeDirection.startToEnd) { + details.setSwipeMaxOffset(200); + } else if (details.swipeDirection == + DataGridRowSwipeDirection.endToStart) { + details.setSwipeMaxOffset(100); + } + return true; + }, + startSwipeActionsBuilder: + (BuildContext context, DataGridRow row, int rowIndex) { + return GestureDetector( + onTap: () { + _employeeDataSource.dataGridRows.insert( + rowIndex, + DataGridRow( + cells: [ + DataGridCell(value: 1011, columnName: 'id'), + DataGridCell(value: 'Tom Bass', columnName: 'name'), + DataGridCell( + value: 'Developer', + columnName: 'designation', + ), + DataGridCell(value: 20000, columnName: 'salary'), + ], + ), + ); + _employeeDataSource.updateDataGridSource(); + }, + child: Container( + color: Colors.greenAccent, + child: Center(child: Icon(Icons.add)), + ), + ); + }, + endSwipeActionsBuilder: + (BuildContext context, DataGridRow row, int rowIndex) { + return GestureDetector( + onTap: () { + _employeeDataSource.dataGridRows.removeAt(rowIndex); + _employeeDataSource.updateDataGridSource(); + }, + child: Container( + color: Colors.redAccent, + child: Center(child: Icon(Icons.delete)), + ), + ); + }, + columns: [ + GridColumn( + columnName: 'id', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'name', - label: Container( + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'name', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'designation', - label: Container( + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( padding: EdgeInsets.symmetric(horizontal: 16.0), alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], - ); - }); + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ); + }, + ), + ); } } From 19084ccfd11f02dd6e91cd2d33d799caeb05e3dd Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 15:25:11 +0530 Subject: [PATCH 11/18] FLUT-1038842-[others][flutter]: Till Export fixed --- Flutter/datagrid/accessibility.md | 184 ++++----- Flutter/datagrid/column-drag-and-drop.md | 357 +++++++++------- Flutter/datagrid/export-to-excel.md | 32 +- .../how-to/custom-widget-on-flutterflow.md | 14 +- Flutter/datagrid/localization.md | 389 +++++++++--------- Flutter/datagrid/paging.md | 44 +- Flutter/datagrid/right-to-left.md | 194 ++++----- Flutter/datagrid/row-height-customization.md | 164 ++++---- Flutter/datagrid/scrolling.md | 42 +- 9 files changed, 691 insertions(+), 729 deletions(-) diff --git a/Flutter/datagrid/accessibility.md b/Flutter/datagrid/accessibility.md index f5835ad5e..e6f0c12f7 100644 --- a/Flutter/datagrid/accessibility.md +++ b/Flutter/datagrid/accessibility.md @@ -11,8 +11,6 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget is designed with comprehensive accessibility features to ensure all users, including those using assistive technologies, can interact with data effectively. This section covers built-in accessibility support and best practices for implementing an accessible data grid experience. -> **Note:** SfDataGrid accessibility features are supported on Android, iOS, and web platforms. Ensure your application targets Flutter 3.0 or higher and syncfusion_flutter_datagrid 20.1.0 or above. - ## Screen reader support The SfDataGrid supports screen readers through the following interactions on Android and iOS platforms: @@ -29,14 +27,14 @@ The SfDataGrid supports screen readers through the following interactions on And The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides sufficient color contrast to make cell content more readable and compliant with WCAG 2.1 AA standards. Customize the appearance of DataGrid elements using the following properties: -* [`currentCellStyle`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridCurrentCellStyle-class.html) — Styling for the currently selected cell -* [`frozenPaneElevation`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneElevation.html) — Shadow depth for frozen panes -* [`frozenPaneLineColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/frozenPaneLineColor.html) — Border color for frozen pane dividers -* [`gridLineColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/gridLineColor.html) — Color of grid lines between cells -* [`headerColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerColor.html) — Background color of column headers -* [`headerHoverColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerHoverColor.html) — Header background color on hover -* [`selectionColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/selectionColor.html) — Background color for selected cells -* [`sortIconColor`](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/sortIconColor.html) — Color of sort indicator icons +* [`currentCellStyle`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/currentCellStyle.html) — Styling for the currently selected cell +* [`frozenPaneElevation`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneElevation.html) — Shadow depth for frozen panes +* [`frozenPaneLineColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/frozenPaneLineColor.html) — Border color for frozen pane dividers +* [`gridLineColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/gridLineColor.html) — Color of grid lines between cells +* [`headerColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/headerColor.html) — Background color of column headers +* [`headerHoverColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/headerHoverColor.html) — Header background color on hover +* [`selectionColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/selectionColor.html) — Background color for selected cells +* [`sortIconColor`](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/sortIconColor.html) — Color of sort indicator icons ## Large fonts @@ -131,40 +129,50 @@ The following example enables keyboard navigation: import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -@override -Widget build(BuildContext context) { - return SfDataGrid( - source: _employeeDataSource, - selectionMode: GridSelectionMode.single, - navigationMode: GridNavigationMode.cell, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text('ID'), - ), - ), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text('Name'), - ), - ), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text('Salary'), - ), + @override + Widget build(BuildContext context) { + return Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + selectionMode: SelectionMode.single, + navigationMode: GridNavigationMode.cell, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], ), - ], - ); -} + ); + } {% endhighlight %} {% endtabs %} @@ -179,61 +187,51 @@ Row heights in [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_dat import 'package:flutter/material.dart'; import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -@override -Widget build(BuildContext context) { - return Theme( - data: ThemeData(visualDensity: VisualDensity.compact), - child: SfDataGrid( - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, + @override + Widget build(BuildContext context) { + return Scaffold( + body: Theme( + data: ThemeData(visualDensity: VisualDensity.compact), + child: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), ), - ), - ), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), ), - ), - ), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), ), - ), - ), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), ), - ), + ], ), - ], - ), - ); -} + ), + ); + } {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/column-drag-and-drop.md b/Flutter/datagrid/column-drag-and-drop.md index 66de86159..7ce93cf05 100644 --- a/Flutter/datagrid/column-drag-and-drop.md +++ b/Flutter/datagrid/column-drag-and-drop.md @@ -20,16 +20,16 @@ The following code example demonstrates the basic setup required for column drag {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; class Employee { Employee(this.id, this.name, this.designation, this.salary); final int id; final String name; final String designation; - final double salary; - + final int salary; + dynamic operator [](String key) { switch (key) { case 'id': @@ -56,56 +56,88 @@ The following code example shows how to enable column drag and drop functionalit {% tabs %} {% highlight Dart %} -late List columns; -late EmployeeDataSource employeeDataSource; - -@override -void initState() { - super.initState(); - List employees = [ - Employee(10001, 'James', 'Project Lead', 20000), - Employee(10002, 'Kathryn', 'Manager', 30000), - Employee(10003, 'Lara', 'Developer', 15000), - Employee(10004, 'Michael', 'Designer', 15000), - ]; - - columns = [ - GridColumn(columnName: 'id', label: const Center(child: Text('ID'))), - GridColumn(columnName: 'name', label: const Center(child: Text('Name'))), - GridColumn(columnName: 'designation', label: const Center(child: Text('Designation'))), - GridColumn(columnName: 'salary', label: const Center(child: Text('Salary'))), - ]; - - employeeDataSource = EmployeeDataSource(employees: employees, columns: columns); -} + List employees = []; + late List columns; + late EmployeeDataSource employeeDataSource; + + @override + void initState() { + super.initState(); -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, + columns = getColumns; + employees = getEmployeeData(); + employeeDataSource = EmployeeDataSource( + employees: employees, columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null && - details.from >= 0 && - details.from < columns.length) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.notifyListeners(); - } - return true; - }, - ), - ); -} + ); + } + + List get getColumns { + return [ + GridColumn( + columnName: 'id', + label: Container( + padding: const EdgeInsets.all(16.0), + alignment: Alignment.center, + child: const Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text('Name'), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text('Salary'), + ), + ), + ]; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.refreshDataGrid(); + } + return true; + }, + ), + ); + } class EmployeeDataSource extends DataGridSource { - EmployeeDataSource({required List employees, required this.columns}) { + EmployeeDataSource({ + required List employees, + required this.columns, + }) { _employees = employees; buildDataGridRows(); } @@ -122,7 +154,8 @@ class EmployeeDataSource extends DataGridSource { columnName: column.columnName, value: employee[column.columnName], ); - }).toList()); + }).toList(), + ); }).toList(); } @@ -136,10 +169,14 @@ class EmployeeDataSource extends DataGridSource { return Container( alignment: Alignment.center, padding: const EdgeInsets.symmetric(horizontal: 8.0), - child: Text( - dataGridCell.value.toString(), - )); - }).toList()); + child: Text(dataGridCell.value.toString()), + ); + }).toList(), + ); + } + + void refreshDataGrid() { + notifyListeners(); } } @@ -148,10 +185,10 @@ class EmployeeDataSource extends DataGridSource { Flutter datagrid shows a checkbox filter in web platform ->**NOTE**: -* To reorder the columns in the DataGrid, create an instance variable to hold the columns and then assign that instance to the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) property instead of directly assigning a list literal. This allows you to reorder the collection within the callback, maintaining the desired column order. -* After reordering columns, rebuild the rows based on the updated columns collection by calling `buildDataGridRows()` and `notifyListeners()`. This is necessary because the column index may change after reordering. By rebuilding the rows, you ensure that the row data aligns correctly with the reordered columns. -* Download the complete sample application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-column-drag-and-drop-in-flutter-datatable-sfdatagrid). +> **Note:** +>* To reorder the columns in the DataGrid, create an instance variable to hold the columns and then assign that instance to the [SfDataGrid.columns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/columns.html) property instead of directly assigning a list literal. This allows you to reorder the collection within the callback, maintaining the desired column order. +>* After reordering columns, rebuild the rows based on the updated columns collection by calling `buildDataGridRows()` and `notifyListeners()`. This is necessary because the column index may change after reordering. By rebuilding the rows, you ensure that the row data aligns correctly with the reordered columns. +>* Download the complete sample application from [GitHub](https://github.com/SyncfusionExamples/how-to-perform-column-drag-and-drop-in-flutter-datatable-sfdatagrid). ## onColumnDragging callback @@ -171,36 +208,36 @@ In the following example, columns cannot be dropped at index 2 (the third column {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - // Prevent dropping at column index 2 - if (details.action == DataGridColumnDragAction.update && - details.to == 2) { - return false; - } - // Handle the drop action - if (details.action == DataGridColumnDragAction.dropped && - details.to != null && - details.from >= 0 && - details.from < columns.length) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.notifyListeners(); - } - return true; - }, - ), - ); -} + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + // Prevent dropping at column index 2 + if (details.action == DataGridColumnDragAction.update && + details.to == 2) { + return false; + } + // Handle the drop action + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ); + } {% endhighlight %} {% endtabs %} @@ -212,46 +249,47 @@ The DataGrid allows you to customize the feedback widget displayed during column {% tabs %} {% highlight Dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - columnDragFeedbackBuilder: (BuildContext context, GridColumn column) { - return Container( - height: 50, - width: column.actualWidth, - color: Colors.grey, - child: const Center( - child: DefaultTextStyle( - style: TextStyle( - fontSize: 14, - color: Colors.pink, - fontWeight: FontWeight.bold), - child: Text('Drag View'), + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + columnDragFeedbackBuilder: (BuildContext context, GridColumn column) { + return Container( + height: 50, + width: column.actualWidth, + color: Colors.teal[400], + child: const Center( + child: DefaultTextStyle( + style: TextStyle( + fontSize: 14, + color: Colors.yellow, + fontWeight: FontWeight.bold, + ), + child: Text('Drag View'), + ), ), - ), - ); - }, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null && - details.from >= 0 && - details.from < columns.length) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.notifyListeners(); - } - return true; - }, - ), - ); -} + ); + }, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), + ); + } {% endhighlight %} {% endtabs %} @@ -262,9 +300,9 @@ Widget build(BuildContext context) { The color and thickness of the drag indicator displayed during column dragging can be customized using the [SfDataGridThemeData.columnDragIndicatorColor](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorColor.html) and [SfDataGridThemeData.columnDragIndicatorStrokeWidth](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridThemeData/columnDragIndicatorStrokeWidth.html) properties. These properties are available in the `syncfusion_flutter_core` package through the [SfDataGridTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataGridTheme-class.html) widget. ->**NOTE**: -* The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the `syncfusion_flutter_core` package. -* Import the theme package: `import 'package:syncfusion_flutter_core/theme.dart';` +> **Note:** +>* The `SfDataGridThemeData` and `SfDataGridTheme` classes are available in the `syncfusion_flutter_core` package. +>* Import the theme package: `import 'package:syncfusion_flutter_core/theme.dart';` The following code demonstrates how to customize the drag indicator appearance: @@ -272,37 +310,38 @@ The following code demonstrates how to customize the drag indicator appearance: {% highlight Dart %} import 'package:syncfusion_flutter_core/theme.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; -@override -Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), - body: SfDataGridTheme( - data: SfDataGridThemeData( - columnDragIndicatorColor: Colors.pink, - columnDragIndicatorStrokeWidth: 3, - ), - child: SfDataGrid( - source: employeeDataSource, - allowColumnsDragging: true, - columns: columns, - onColumnDragging: (DataGridColumnDragDetails details) { - if (details.action == DataGridColumnDragAction.dropped && - details.to != null && - details.from >= 0 && - details.from < columns.length) { - final GridColumn rearrangeColumn = columns[details.from]; - columns.removeAt(details.from); - columns.insert(details.to!, rearrangeColumn); - employeeDataSource.buildDataGridRows(); - employeeDataSource.notifyListeners(); - } - return true; - }, + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: SfDataGridTheme( + data: SfDataGridThemeData( + columnDragIndicatorColor: Colors.pink, + columnDragIndicatorStrokeWidth: 3, + ), + child: SfDataGrid( + source: employeeDataSource, + allowColumnsDragging: true, + columns: columns, + onColumnDragging: (DataGridColumnDragDetails details) { + if (details.action == DataGridColumnDragAction.dropped && + details.to != null && + details.from >= 0 && + details.from < columns.length) { + final GridColumn rearrangeColumn = columns[details.from]; + columns.removeAt(details.from); + columns.insert(details.to!, rearrangeColumn); + employeeDataSource.buildDataGridRows(); + employeeDataSource.notifyListeners(); + } + return true; + }, + ), ), - ), - ); -} + ); + } {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index 81a8171f8..25ddbb93d 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -21,11 +21,10 @@ dependencies: syncfusion_flutter_datagrid: ^xx.x.xx syncfusion_flutter_datagrid_export: ^xx.x.xx -syncfusion_flutter_xlsio: ^xx.x.xx {% endhighlight %} ->**NOTE:** Replace **xx.x.xx** with the latest version of the packages from [pub.dev](https://pub.dev). Ensure all three packages have compatible versions. Requires Flutter 3.0 and above. +> **Note:** Replace **xx.x.xx** with the latest version of the packages from [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export). Ensure all three packages have compatible versions. Requires Flutter 3.0 and above. **Import package** @@ -34,7 +33,6 @@ Import the following packages in your Dart code. {% tabs %} {% highlight Dart %} -import 'dart:io'; import 'package:syncfusion_flutter_datagrid_export/export.dart'; import 'package:syncfusion_flutter_xlsio/xlsio.dart'; @@ -45,32 +43,8 @@ Export the `SfDataGrid` by using the following extension methods present in the * [exportToExcelWorkbook](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorkbook.html) * [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) - - -**Create a helper method for saving files** - -Create a helper method to save and launch the exported Excel file. This method handles platform-specific file operations. - -{% tabs %} -{% highlight Dart %} - -class FileHelper { - static Future saveAndLaunchFile(List bytes, String fileName) async { - final String path = (await getApplicationDocumentsDirectory()).path; - final File file = File('$path/$fileName'); - await file.writeAsBytes(bytes, flush: true); - - if (await file.exists()) { - // Open the file with the default application - await OpenFile.open('$path/$fileName'); - } - } -} - -{% endhighlight %} -{% endtabs %} ->**NOTE:** You need to add the `path_provider` and `open_file` packages to your pubspec.yaml to use the helper method above. +> **Note:** You need to add the `path_provider` and `open_file` packages to your pubspec.yaml to use the helper method above. **Add GlobalKey for the DataGrid** @@ -292,7 +266,7 @@ await FileHelper.saveAndLaunchFile(bytes, 'SelectedRows.xlsx'); {% endhighlight %} {% endtabs %} ->**NOTE:** Ensure row selection is enabled in the SfDataGrid by setting the `selectionMode` property to `SelectionMode.multiple` or `SelectionMode.single`. +> **Note:** Ensure row selection is enabled in the SfDataGrid by setting the `selectionMode` property to `SelectionMode.multiple` or `SelectionMode.single`. ## Row height and column width customization diff --git a/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md b/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md index 502333dd0..d718330ef 100644 --- a/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md +++ b/Flutter/datagrid/how-to/custom-widget-on-flutterflow.md @@ -13,7 +13,7 @@ documentation: ug [FlutterFlow](https://app.flutterflow.io/dashboard) enables you to create native applications using its graphical interface, reducing the need to write extensive amounts of code. Additionally, it offers the capability to include custom widgets that are not included in the default [FlutterFlow](https://app.flutterflow.io/dashboard) widget collection. This article explains how to incorporate the SfDataGrid widget as a custom widget in FlutterFlow. ->**Note**: You need an active FlutterFlow account and basic knowledge of Flutter development to follow this guide. Refer to the [SDK version compatibility](https://help.syncfusion.com/flutter/system-requirements#sdk-version-compatibility) to ensure your FlutterFlow's Flutter version is compatible with the Syncfusion Flutter DataGrid package. +> **Note:** You need an active FlutterFlow account and basic knowledge of Flutter development to follow this guide. Refer to the [SDK version compatibility](https://help.syncfusion.com/flutter/system-requirements#sdk-version-compatibility) to ensure your FlutterFlow's Flutter version is compatible with the Syncfusion Flutter DataGrid package. ### Create a new project @@ -37,9 +37,9 @@ Navigate to the [FlutterFlow dashboard](https://app.flutterflow.io/dashboard) an ![Version](how-to-section-images/copy-version.png) 3. Paste the copied dependency into the text editor, then click `Refresh` and `Save` it. ->**Note**: If you need a specific version instead of the latest, remove the caret (^) prefix in the version number. For example, change `^21.3.0` to `21.3.0` to lock to that exact version. - ->**Note**: The SfDataGrid package depends on the [Syncfusion Flutter Core](https://pub.dev/packages/syncfusion_flutter_core) package. Make sure to add it as a dependency using the same steps above. +>**Note**: +>- If you need a specific version instead of the latest, remove the caret (^) prefix in the version number. For example, change `^21.3.0` to `21.3.0` to lock to that exact version. +>- The SfDataGrid package depends on the [Syncfusion Flutter Core](https://pub.dev/packages/syncfusion_flutter_core) package. Make sure to add it as a dependency using the same steps above. ![Dependency](how-to-section-images/dependency.png) @@ -77,9 +77,3 @@ Navigate to the [FlutterFlow dashboard](https://app.flutterflow.io/dashboard) an 5. Run your FlutterFlow app to verify the SfDataGrid widget displays correctly. ![Page](how-to-section-images/page.png) - -## See also - -- [Syncfusion Flutter DataGrid documentation](https://help.syncfusion.com/flutter/datagrid/overview) -- [SfDataGrid GitHub examples](https://github.com/syncfusion/flutter-examples/tree/master/lib/samples/datagrid) -- [Syncfusion Flutter DataGrid API reference](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/) diff --git a/Flutter/datagrid/localization.md b/Flutter/datagrid/localization.md index 476757542..0bc5f668e 100644 --- a/Flutter/datagrid/localization.md +++ b/Flutter/datagrid/localization.md @@ -22,7 +22,7 @@ To use `flutter_localizations` and `syncfusion_localizations`, add the package a dependencies: flutter_localizations: sdk: flutter -syncfusion_localizations: ^24.2.7 +syncfusion_localizations: ^34.1.29 {% endhighlight %} @@ -48,13 +48,9 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation localizationsDelegates: const [ GlobalMaterialLocalizations.delegate, GlobalWidgetsLocalizations.delegate, - SfGlobalLocalizations.delegate - ], - supportedLocales: const [ - Locale('zh'), - Locale('ar'), - Locale('ja'), + SfGlobalLocalizations.delegate, ], + supportedLocales: const [Locale('zh'), Locale('ar'), Locale('ja')], locale: const Locale('ar'), home: Scaffold( appBar: AppBar( @@ -69,34 +65,40 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation allowFiltering: true, columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: const EdgeInsets.all(16.0), - alignment: Alignment.center, - child: const Text( - 'ID', - ))), + columnName: 'id', + label: Container( + padding: const EdgeInsets.all(16.0), + alignment: Alignment.center, + child: const Text('ID'), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: const EdgeInsets.all(8.0), - alignment: Alignment.center, - child: const Text('Name'))), + columnName: 'name', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text('Name'), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: const EdgeInsets.all(8.0), - alignment: Alignment.center, - child: const Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: const EdgeInsets.all(8.0), - alignment: Alignment.center, - child: const Text('Salary'))), + columnName: 'salary', + label: Container( + padding: const EdgeInsets.all(8.0), + alignment: Alignment.center, + child: const Text('Salary'), + ), + ), ], ), ), @@ -140,20 +142,75 @@ Next, import the `flutter_localizations` library and specify [localizationsDeleg import 'package:flutter_localizations/flutter_localizations.dart'; -final int rowsPerPage = 15; + List _employees = []; + late EmployeeDataSource _employeeDataSource; + final int rowsPerPage = 15; -class Employee { - Employee({ - required this.id, - required this.name, - required this.designation, - required this.salary, - }); - final int id; - final String name; - final String designation; - final double salary; -} + @override + void initState() { + super.initState(); + _employees = getEmployeeData(); + _employeeDataSource = EmployeeDataSource(employeeData: _employees); + } + + @override + Widget build(BuildContext context) { + return MaterialApp( + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: const [Locale('zh'), Locale('ar'), Locale('ja')], + locale: const Locale('ar'), + home: Scaffold( + appBar: AppBar(title: const Text('DataPager')), + body: LayoutBuilder( + builder: (context, constraints) { + return Column( + children: [ + SizedBox( + height: constraints.maxHeight - 60, + width: constraints.maxWidth, + child: SfDataGrid( + source: _employeeDataSource, + allowFiltering: true, + columns: [ + GridColumn( + columnName: 'id', + label: Center(child: Text('ID')), + ), + GridColumn( + columnName: 'name', + label: Center(child: Text('Name')), + ), + GridColumn( + columnName: 'designation', + label: Center(child: Text('Designation')), + ), + GridColumn( + columnName: 'salary', + label: Center(child: Text('Salary')), + ), + ], + ), + ), + SizedBox( + height: 60, + width: constraints.maxWidth, + child: SfDataPager( + delegate: _employeeDataSource, + pageCount: _employeeDataSource.rows.length / rowsPerPage, + visibleItemsCount: 5, + direction: Axis.horizontal, + ), + ), + ], + ); + }, + ), + ), + ); + } class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { @@ -164,12 +221,19 @@ class EmployeeDataSource extends DataGridSource { @override List get rows => _employeeData - .map((dataRow) => DataGridRow(cells: [ + .map( + (dataRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataRow.id), DataGridCell(columnName: 'name', value: dataRow.name), - DataGridCell(columnName: 'designation', value: dataRow.designation), - DataGridCell(columnName: 'salary', value: dataRow.salary), - ])) + DataGridCell( + columnName: 'designation', + value: dataRow.designation, + ), + DataGridCell(columnName: 'salary', value: dataRow.salary), + ], + ), + ) .toList(); @override @@ -186,76 +250,6 @@ class EmployeeDataSource extends DataGridSource { } } -@override -Widget build(BuildContext context) { - final EmployeeDataSource _employeeDataSource = EmployeeDataSource( - employeeData: [ - Employee(id: 10001, name: 'James', designation: 'Project Lead', salary: 20000), - Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), - Employee(id: 10005, name: 'Martin', designation: 'Developer', salary: 15000), - ], - ); - - return MaterialApp( - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: const [ - Locale('zh'), - Locale('ar'), - Locale('ja'), - ], - locale: const Locale('zh'), - home: Scaffold( - appBar: AppBar( - title: const Text('DataPager'), - ), - body: LayoutBuilder(builder: (context, constraints) { - return Column(children: [ - SizedBox( - height: constraints.maxHeight - 60, - width: constraints.maxWidth, - child: SfDataGrid( - source: _employeeDataSource, - columns: const [ - GridColumn( - columnName: 'id', - label: Center(child: Text('ID')), - ), - GridColumn( - columnName: 'name', - label: Center(child: Text('Name')), - ), - GridColumn( - columnName: 'designation', - label: Center(child: Text('Designation')), - ), - GridColumn( - columnName: 'salary', - label: Center(child: Text('Salary')), - ), - ], - ), - ), - Container( - height: 60, - width: constraints.maxWidth, - child: SfDataPager( - delegate: _employeeDataSource, - pageCount: _employeeDataSource.rows.length / rowsPerPage, - visibleItemsCount: 5, - direction: Axis.horizontal, - ), - ) - ]); - }), - ), - ); -} - {% endhighlight %} {% endtabs %} @@ -274,7 +268,7 @@ To use `syncfusion_localizations`, add it as a dependency to the `pubspec.yaml` dependencies: flutter_localizations: sdk: flutter -syncfusion_localizations: ^24.2.7 +syncfusion_localizations: ^34.1.29 {% endhighlight %} @@ -297,18 +291,73 @@ Then, declare the [SfGlobalLocalizations.delegate](https://pub.dev/documentation final int rowsPerPage = 15; class Employee { - Employee({ - required this.id, - required this.name, - required this.designation, - required this.salary, - }); + Employee(this.id, this.name, this.designation, this.salary); + final int id; final String name; final String designation; - final double salary; + final int salary; } + @override + Widget build(BuildContext context) { + return MaterialApp( + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + SfGlobalLocalizations.delegate, + ], + supportedLocales: const [Locale('zh'), Locale('ar'), Locale('ja')], + locale: const Locale('zh'), + home: Scaffold( + appBar: AppBar(title: const Text('DataPager')), + body: LayoutBuilder( + builder: (context, constraints) { + return Column( + children: [ + SizedBox( + height: constraints.maxHeight - 60, + width: constraints.maxWidth, + child: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'id', + label: Center(child: Text('ID')), + ), + GridColumn( + columnName: 'name', + label: Center(child: Text('Name')), + ), + GridColumn( + columnName: 'designation', + label: Center(child: Text('Designation')), + ), + GridColumn( + columnName: 'salary', + label: Center(child: Text('Salary')), + ), + ], + ), + ), + SizedBox( + height: 60, + width: constraints.maxWidth, + child: SfDataPager( + delegate: _employeeDataSource, + pageCount: _employeeDataSource.rows.length / rowsPerPage, + visibleItemsCount: 5, + direction: Axis.horizontal, + ), + ), + ], + ); + }, + ), + ), + ); + } + class EmployeeDataSource extends DataGridSource { EmployeeDataSource({required List employeeData}) { _employeeData = employeeData; @@ -318,12 +367,19 @@ class EmployeeDataSource extends DataGridSource { @override List get rows => _employeeData - .map((dataRow) => DataGridRow(cells: [ + .map( + (dataRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataRow.id), DataGridCell(columnName: 'name', value: dataRow.name), - DataGridCell(columnName: 'designation', value: dataRow.designation), - DataGridCell(columnName: 'salary', value: dataRow.salary), - ])) + DataGridCell( + columnName: 'designation', + value: dataRow.designation, + ), + DataGridCell(columnName: 'salary', value: dataRow.salary), + ], + ), + ) .toList(); @override @@ -340,77 +396,6 @@ class EmployeeDataSource extends DataGridSource { } } -@override -Widget build(BuildContext context) { - final EmployeeDataSource _employeeDataSource = EmployeeDataSource( - employeeData: [ - Employee(id: 10001, name: 'James', designation: 'Project Lead', salary: 20000), - Employee(id: 10002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 10003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 10004, name: 'Michael', designation: 'Designer', salary: 15000), - Employee(id: 10005, name: 'Martin', designation: 'Developer', salary: 15000), - ], - ); - - return MaterialApp( - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - SfGlobalLocalizations.delegate, - ], - supportedLocales: const [ - Locale('zh'), - Locale('ar'), - Locale('ja'), - ], - locale: const Locale('zh'), - home: Scaffold( - appBar: AppBar( - title: const Text('DataPager'), - ), - body: LayoutBuilder(builder: (context, constraints) { - return Column(children: [ - SizedBox( - height: constraints.maxHeight - 60, - width: constraints.maxWidth, - child: SfDataGrid( - source: _employeeDataSource, - columns: const [ - GridColumn( - columnName: 'id', - label: Center(child: Text('ID')), - ), - GridColumn( - columnName: 'name', - label: Center(child: Text('Name')), - ), - GridColumn( - columnName: 'designation', - label: Center(child: Text('Designation')), - ), - GridColumn( - columnName: 'salary', - label: Center(child: Text('Salary')), - ), - ], - ), - ), - Container( - height: 60, - width: constraints.maxWidth, - child: SfDataPager( - delegate: _employeeDataSource, - pageCount: _employeeDataSource.rows.length / rowsPerPage, - visibleItemsCount: 5, - direction: Axis.horizontal, - ), - ) - ]); - }), - ), - ); -} - {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/paging.md b/Flutter/datagrid/paging.md index 20ddafb5f..be4760884 100644 --- a/Flutter/datagrid/paging.md +++ b/Flutter/datagrid/paging.md @@ -18,7 +18,7 @@ The Datagrid performs paging of data using the `SfDataPager`. To enable paging, * Set the number of buttons that should be displayed in view by setting the [SfDataPager.visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html) property. * Load the data for a specific page in the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method. This method returns a `Future` and is called when navigating between pages in the data pager. -N> The `SfDataPager.visibleItemsCount` property default value is 5. Also, ensure that the [syncfusion_flutter_datagrid](https://pub.dev/packages/syncfusion_flutter_datagrid) and [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) packages are added to your `pubspec.yaml` file. +> **Note:** The `SfDataPager.visibleItemsCount` property default value is 5. Also, ensure that the [syncfusion_flutter_datagrid](https://pub.dev/packages/syncfusion_flutter_datagrid) and [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) packages are added to your `pubspec.yaml` file. The following code example illustrates using the `SfDataPager` with the Datagrid control: @@ -26,35 +26,12 @@ The following code example illustrates using the `SfDataPager` with the Datagrid {% highlight Dart %} import 'package:intl/intl.dart'; -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - -// OrderInfo model class -class OrderInfo { - OrderInfo({ - required this.orderID, - required this.customerID, - required this.orderDate, - required this.freight, - }); - - final int orderID; - final String customerID; - final DateTime orderDate; - final double freight; -} final int _rowsPerPage = 15; final double _dataPagerHeight = 60.0; - List _orders = []; // Populate with sample data - List _paginatedOrders = []; - late final OrderInfoDataSource _orderInfoDataSource; - - @override - void initState() { - super.initState(); - // Initialize the data source after populating _orders - _orderInfoDataSource = OrderInfoDataSource(); - } + List _orders = []; + List _paginatedOrders = []; + final OrderInfoDataSource _orderInfoDataSource = OrderInfoDataSource(); @override Widget build(BuildContext context) { @@ -68,7 +45,7 @@ class OrderInfo { height: _dataPagerHeight, child: SfDataPager( delegate: _orderInfoDataSource, - pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), + pageCount: _orders.length / _rowsPerPage, direction: Axis.horizontal, )) ]); @@ -121,8 +98,7 @@ class OrderInfo { class OrderInfoDataSource extends DataGridSource { OrderInfoDataSource() { - int endIndex = _orders.length < _rowsPerPage ? _orders.length : _rowsPerPage; - _paginatedOrders = _orders.getRange(0, endIndex).toList(growable: false); + _paginatedOrders = _orders.getRange(0, 19).toList(growable: false); buildPaginatedDataGridRows(); } @@ -368,8 +344,7 @@ class OrderInfoDataSource extends DataGridSource { ![flutter datapager with asynchronous loading](images/paging/flutter-datapager-asynchronous-loading.gif) ->**NOTE** - Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-show-loading-indicator-on-loading-page-in-flutter-datatable). +> **Note:** Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-show-loading-indicator-on-loading-page-in-flutter-datatable). ## Programmatic page navigation @@ -436,8 +411,7 @@ Show the dropdown button option to select a different number of rows per page by Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/availableRowsPerPage.html) property to define the list of numbers to be displayed in the drop-down. The default value of the `availableRowsPerPage` property is [10, 15, 20]. ->**NOTE** - You can view the dropdown button option by horizontally scrolling the DataPager. The dropdown button option is not supported if the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) is vertical. Also, only values that are present in the `availableRowsPerPage` list can be selected from the dropdown. +> **Note:** You can view the dropdown button option by horizontally scrolling the DataPager. The dropdown button option is not supported if the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) is vertical. Also, only values that are present in the `availableRowsPerPage` list can be selected from the dropdown. {% tabs %} {% highlight Dart %} @@ -685,7 +659,7 @@ The padding between the page items including navigation page items such as first {% endhighlight %} {% endtabs %} -**Note:** The default value of `SfDataPager.itemPadding` is 5.0. +**Note:** The default value of `SfDataPager.itemPadding` is `5.0`. ### Set the height and width of the page items diff --git a/Flutter/datagrid/right-to-left.md b/Flutter/datagrid/right-to-left.md index c52d3b6a8..0f8349129 100644 --- a/Flutter/datagrid/right-to-left.md +++ b/Flutter/datagrid/right-to-left.md @@ -11,15 +11,13 @@ documentation: ug SfDataGrid supports right-to-left (RTL) rendering. When RTL is enabled, columns will be rendered in reverse order, scrollbars will appear on the left side, and text alignment will be mirrored accordingly. -> **Note:** This feature requires Flutter 2.0+ and syncfusion_flutter_datagrid 19.1.0 or later. - ## RTL rendering ways Right-to-left rendering can be switched in the following ways: ### Wrapping the SfDataGrid with the Directionality widget -Wrap the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget inside the [Directionality](https://api.flutter.dev/flutter/widgets/Directionality-class.html) widget and set the [textDirection](https://api.flutter.dev/flutter/widgets/Directionality/textDirection.html) property to [TextDirection.rtl](https://api.flutter.dev/flutter/dart-ui/TextDirection-class.html) to enable RTL rendering. +Wrap the [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) widget inside the [Directionality](https://api.flutter.dev/flutter/widgets/Directionality-class.html) widget and set the [textDirection](https://api.flutter.dev/flutter/widgets/Directionality/textDirection.html) property to [TextDirection.rtl](https://api.flutter.dev/flutter/dart-ui/TextDirection.html#rtl) to enable RTL rendering. {% tabs %} {% highlight Dart %} @@ -29,41 +27,48 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; @override Widget build(BuildContext context) { return Directionality( - textDirection: TextDirection.rtl, - child: SfDataGrid( - source: _employeeDataSource, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text( - 'ID', - ))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ])); + textDirection: TextDirection.rtl, + child: Scaffold( + body: SfDataGrid( + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ), + ); } {% endhighlight %} @@ -91,68 +96,65 @@ Import the `flutter_localizations` library and configure [localizationsDelegates import 'package:syncfusion_flutter_datagrid/datagrid.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; -void main() { - runApp(const MyApp()); -} - -class MyApp extends StatelessWidget { - const MyApp({Key? key}) : super(key: key); - @override Widget build(BuildContext context) { return MaterialApp( - localizationsDelegates: [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: [ - Locale('en'), - Locale('ar'), - Locale('fa'), - Locale('he'), - Locale('ps'), - Locale('ur'), - ], - locale: Locale('ar'), - home: Scaffold( - appBar: AppBar( - title: Text('RTL DataGrid'), - ), - body: SfDataGrid( - source: _employeeDataSource, - columnWidthMode: ColumnWidthMode.fill, - columns: [ - GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.all(16.0), - alignment: Alignment.center, - child: Text('ID'))), - GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Name'))), - GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.all(8.0), - alignment: Alignment.center, - child: Text('Salary'))), - ]), - )); + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ], + supportedLocales: [ + Locale('en'), + Locale('ar'), + Locale('fa'), + Locale('he'), + Locale('ps'), + Locale('ur'), + ], + locale: Locale('ar'), + home: Scaffold( + appBar: AppBar(title: Text('RTL DataGrid')), + body: SfDataGrid( + source: _employeeDataSource, + columnWidthMode: ColumnWidthMode.fill, + columns: [ + GridColumn( + columnName: 'id', + label: Container( + padding: EdgeInsets.all(16.0), + alignment: Alignment.center, + child: Text('ID'), + ), + ), + GridColumn( + columnName: 'name', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Name'), + ), + ), + GridColumn( + columnName: 'designation', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), + GridColumn( + columnName: 'salary', + label: Container( + padding: EdgeInsets.all(8.0), + alignment: Alignment.center, + child: Text('Salary'), + ), + ), + ], + ), + ), + ); } -} {% endhighlight %} {% endtabs %} \ No newline at end of file diff --git a/Flutter/datagrid/row-height-customization.md b/Flutter/datagrid/row-height-customization.md index 3a5242839..68833e91d 100644 --- a/Flutter/datagrid/row-height-customization.md +++ b/Flutter/datagrid/row-height-customization.md @@ -11,8 +11,6 @@ documentation: ug This section explains options to customize the header row height and the row height of all the grid rows or particular rows based on your requirements. -> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` - ## Set the height for a specific row The row height of a particular row can be set by using the [SfDataGrid.onQueryRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/onQueryRowHeight.html) callback. @@ -336,7 +334,7 @@ class CustomColumnSizer extends ColumnSizer { {% endhighlight %} {% endtabs %} -> **NOTE:** The `CustomColumnSizer` is a custom class that should be added to your dart file. You can download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-different-text-style-in-Flutter-DataTable-sfdatagrid). +> **Note:** The `CustomColumnSizer` is a custom class that should be added to your dart file. You can download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-different-text-style-in-Flutter-DataTable-sfdatagrid). ![flutter datagrid shows auto-fitting the row height based on different text style](images/row-height-customization/flutter-datagrid-autofit-textstyle-customization.png) @@ -353,8 +351,6 @@ dependencies: {% endhighlight %} -> **NOTE:** Requires Flutter 2.0 or later and Dart 2.12 or later. The `intl` package provides internationalized message support for Dart and Flutter applications. - Import the required packages: {% tabs %} @@ -487,7 +483,7 @@ class CustomColumnSizer extends ColumnSizer { {% endhighlight %} {% endtabs %} -> **NOTE:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-formatted-value-in-Flutter-datatable-sfdatagrid). +> **Note:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-fit-the-rows-based-on-the-formatted-value-in-Flutter-datatable-sfdatagrid). ![flutter datagrid shows auto-fitting the row height based on formatted cell value](images/row-height-customization/flutter-datagrid-formatted-cellvalue.png) @@ -495,7 +491,7 @@ class CustomColumnSizer extends ColumnSizer { [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows you to customize the height of the header row by using the [headerRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerRowHeight.html) property. -> **NOTE:** The default value of `headerRowHeight` is `49.0`. You can set any double value to customize the header row height according to your requirements. +> **Note:** The default value of `headerRowHeight` is `49.0`. You can set any double value to customize the header row height according to your requirements. {% tabs %} {% highlight dart %} @@ -556,7 +552,7 @@ class CustomColumnSizer extends ColumnSizer { You can customize the height of the grid rows in `SfDataGrid` by using the [rowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowHeight.html) property. -> **NOTE:** The default value of `rowHeight` is `49.0`. Use this property to set a uniform height for all data rows (excluding the header row). For variable heights based on content, use the `onQueryRowHeight` callback instead. +> **Note:** The default value of `rowHeight` is `49.0`. Use this property to set a uniform height for all data rows (excluding the header row). For variable heights based on content, use the `onQueryRowHeight` callback instead. {% tabs %} {% highlight Dart %} @@ -625,7 +621,7 @@ Refresh a specific row and its height by using the [DataGridController.refreshRo When you call the `refreshRow` method, the `onQueryRowHeight` callback will be invoked for that specific row, allowing auto-height calculation to be recalculated. -> **NOTE:** When calling `refreshRow`, ensure the rowIndex is within the valid range (0 to dataGridRows.length - 1). Calling with an out-of-bounds rowIndex may not refresh the intended row. Use `recalculateRowHeight: true` to recalculate row heights based on updated content. +> **Note:** When calling `refreshRow`, ensure the rowIndex is within the valid range (0 to dataGridRows.length - 1). Calling with an out-of-bounds rowIndex may not refresh the intended row. Use `recalculateRowHeight: true` to recalculate row heights based on updated content. In the following example, row data is updated when `refreshRow` is called in the `onPressed` callback of the `TextButton`: @@ -781,73 +777,72 @@ In the following example, the row data is refreshed along with its row height wh @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: const Text('Syncfusion Flutter DataGrid'), - ), - body: Column(children: [ + appBar: AppBar(title: const Text('Syncfusion Flutter DataGrid')), + body: Column( + children: [ TextButton( - child: const Text('Update cell value'), - onPressed: () { - _employees[0].id = 1010; - _employees[0].name = 'Maria Anders'; - _employees[0].designation = 'Sales Representative'; - _employees[0].salary = 25000; - _controller.refreshRow(0, recalculateRowHeight: true); - _employeeDataSource.buildDataGridSource(_employees); - _employeeDataSource.updateDataGridSource(); - }), + child: const Text('Update cell value'), + onPressed: () { + _employees[0].id = 1010; + _employees[0].name = 'Maria Anders'; + _employees[0].designation = 'Sales Representative'; + _employees[0].salary = 25000; + _controller.refreshRow(0, recalculateRowHeight: true); + _employeeDataSource.buildDataGridSource(_employees); + _employeeDataSource.updateDataGridSource(); + }, + ), Expanded( - child: SfDataGrid( - source: _employeeDataSource, - controller: _controller, - columnSizer: _columnSizer, - columnWidthMode: ColumnWidthMode.auto, - onQueryRowHeight: (RowHeightDetails details) { - if (details.rowIndex == 0) { - return 100.0; - } - - return 50.0; - }, - columns: [ + child: SfDataGrid( + source: _employeeDataSource, + controller: _controller, + columnWidthMode: ColumnWidthMode.auto, + onQueryRowHeight: (RowHeightDetails details) { + if (details.rowIndex == 0) { + return 100.0; + } + + return 50.0; + }, + columns: [ GridColumn( - columnName: 'id', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'id', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('ID', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Name', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerLeft, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), + columnName: 'designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerLeft, + child: Text('Designation', overflow: TextOverflow.ellipsis), + ), + ), GridColumn( - columnName: 'salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.centerRight, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ])) - ])); + columnName: 'salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.centerRight, + child: Text('Salary', overflow: TextOverflow.ellipsis), + ), + ), + ], + ), + ), + ], + ), + ); } class EmployeeDataSource extends DataGridSource { @@ -857,14 +852,22 @@ class EmployeeDataSource extends DataGridSource { void buildDataGridSource(List employees) { dataGridRows = employees - .map((dataGridRow) => DataGridRow(cells: [ + .map( + (dataGridRow) => DataGridRow( + cells: [ DataGridCell(columnName: 'id', value: dataGridRow.id), DataGridCell(columnName: 'name', value: dataGridRow.name), DataGridCell( - columnName: 'designation', value: dataGridRow.designation), + columnName: 'designation', + value: dataGridRow.designation, + ), DataGridCell( - columnName: 'salary', value: dataGridRow.salary), - ])) + columnName: 'salary', + value: dataGridRow.salary, + ), + ], + ), + ) .toList(); } @@ -876,9 +879,10 @@ class EmployeeDataSource extends DataGridSource { @override DataGridRowAdapter? buildRow(DataGridRow row) { return DataGridRowAdapter( - cells: row.getCells().map((dataGridCell) { - return Container( - alignment: (dataGridCell.columnName == 'id' || + cells: row.getCells().map((dataGridCell) { + return Container( + alignment: + (dataGridCell.columnName == 'id' || dataGridCell.columnName == 'salary') ? Alignment.centerRight : Alignment.centerLeft, @@ -886,8 +890,10 @@ class EmployeeDataSource extends DataGridSource { child: Text( dataGridCell.value.toString(), overflow: TextOverflow.ellipsis, - )); - }).toList()); + ), + ); + }).toList(), + ); } void updateDataGridSource() { diff --git a/Flutter/datagrid/scrolling.md b/Flutter/datagrid/scrolling.md index 98a26b6b8..351711f07 100644 --- a/Flutter/datagrid/scrolling.md +++ b/Flutter/datagrid/scrolling.md @@ -15,7 +15,7 @@ SfDataGrid provides support to scroll the content in both horizontal and vertica You can show horizontal and vertical scrollbars always by using the [SfDataGrid.isScrollbarAlwaysShown](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/isScrollbarAlwaysShown.html) property. When the `isScrollbarAlwaysShown` is set to `false`, the scrollbar will be shown during scrolling and will fade out otherwise. When it is `true`, the scrollbar will always be visible and never fade out even after scrolling. -> **NOTE:** The default value of `isScrollbarAlwaysShown` is `false`. This ensures scrollbars appear only during active scrolling for a cleaner UI. +> **Note:** The default value of `isScrollbarAlwaysShown` is `false`. This ensures scrollbars appear only during active scrolling for a cleaner UI. {% tabs %} {% highlight Dart %} @@ -73,7 +73,7 @@ You can show horizontal and vertical scrollbars always by using the [SfDataGrid. You can control the visibility of horizontal and vertical scrollbars in the DataGrid by setting the [SfDataGrid.showVerticalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showVerticalScrollbar.html) and [SfDataGrid.showHorizontalScrollbar](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/showHorizontalScrollbar.html) properties. To disable the default scrollbar of the `SingleChildScrollView`, wrap the `ScrollConfiguration` as the parent for the `SfDataGrid` and set the scrollbars to `false`. This prevents duplicate scrollbars from appearing. -> **NOTE:** The default value of `showVerticalScrollbar` and `showHorizontalScrollbar` is `true`. Setting these to `false` disables only the DataGrid's internal scrollbars. +> **Note:** The default value of `showVerticalScrollbar` and `showHorizontalScrollbar` is `true`. Setting these to `false` disables only the DataGrid's internal scrollbars. The following code snippets demonstrate how to hide the scrollbars in the DataGrid: @@ -136,7 +136,7 @@ The following code snippets demonstrate how to hide the scrollbars in the DataGr SfDataGrid allows you to set the [ScrollPhysics](https://api.flutter.dev/flutter/widgets/ScrollPhysics-class.html) for horizontal and vertical scrollbars to control how the scroll view should respond to user input by using [horizontalScrollPhysics](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/horizontalScrollPhysics.html) and [verticalScrollPhysics](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/verticalScrollPhysics.html) properties respectively. -> **NOTE:** The default values of `horizontalScrollPhysics` and `verticalScrollPhysics` properties are `AlwaysScrollableScrollPhysics()`. +> **Note:** The default values of `horizontalScrollPhysics` and `verticalScrollPhysics` properties are `AlwaysScrollableScrollPhysics()`. The following example shows how to disable the horizontal and vertical scrolling by setting `NeverScrollableScrollPhysics()`. @@ -201,9 +201,9 @@ The Flutter DataTable provides support to scroll to a particular row and column Scroll programmatically to a particular cell by passing the row and column index to the [DataGridController.scrollToCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToCell.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -> **NOTE:** The default value of `canAnimate` is `false`. If you specify a rowIndex or columnIndex that exceeds the valid range, the scrolling will not occur. - -> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` +> **Note:** +>- The default value of `canAnimate` is `false`. If you specify a rowIndex or columnIndex that exceeds the valid range, the scrolling will not occur. +>- Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` {% tabs %} {% highlight Dart %} @@ -276,7 +276,7 @@ Scroll programmatically to a particular cell by passing the row and column index Scroll programmatically to a particular row by passing the row index to the [DataGridController.scrollToRow](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToRow.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -> **NOTE:** The default value of `canAnimate` is `false`. If the specified rowIndex exceeds the total number of rows, the scrolling will not occur. +> **Note:** The default value of `canAnimate` is `false`. If the specified rowIndex exceeds the total number of rows, the scrolling will not occur. {% tabs %} {% highlight Dart %} @@ -347,7 +347,7 @@ Scroll programmatically to a particular row by passing the row index to the [Dat Scroll programmatically to a particular column by passing the column index to the [DataGridController.scrollToColumn](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToColumn.html) method. SfDataGrid allows you to enable or disable the scrolling animation by passing `true` to the `canAnimate` parameter. -> **NOTE:** The default value of `canAnimate` is `false`. If the specified columnIndex exceeds the total number of columns, the scrolling will not occur. +> **Note:** The default value of `canAnimate` is `false`. If the specified columnIndex exceeds the total number of columns, the scrolling will not occur. {% tabs %} {% highlight Dart %} @@ -425,7 +425,7 @@ The `SfDataGrid` allows positioning of the scrolled row or column in view progra * `center` - Position the row/column at the center of the DataGrid. * `end` - Position the row/column at the end of the DataGrid. -> **NOTE:** The default value of `DataGridScrollPosition` is `start`. +> **Note:** The default value of `DataGridScrollPosition` is `start`. {% tabs %} {% highlight Dart %} @@ -570,7 +570,7 @@ The Flutter DataTable supports scrolling programmatically to a particular vertic The Flutter DataTable supports scrolling programmatically to a particular horizontal offset by passing the offset value to the [DataGridController.scrollToHorizontalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/scrollToHorizontalOffset.html) method. You can enable the scrolling animation by passing `true` to the `canAnimate` parameter. -> **NOTE:** The default value of `canAnimate` is `false`. The offset value should be non-negative and not exceed the maximum scrollable extent. +> **Note:** The default value of `canAnimate` is `false`. The offset value should be non-negative and not exceed the maximum scrollable extent. {% tabs %} {% highlight Dart %} @@ -637,13 +637,13 @@ The Flutter DataTable supports scrolling programmatically to a particular horizo {% endhighlight %} {% endtabs %} -> **NOTE:** The vertical and horizontal scroll offsets can be retrieved using the [DataGridController.verticalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/verticalOffset.html) and [DataGridController.horizontalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/horizontalOffset.html) properties respectively. +> **Note:** The vertical and horizontal scroll offsets can be retrieved using the [DataGridController.verticalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/verticalOffset.html) and [DataGridController.horizontalOffset](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/horizontalOffset.html) properties respectively. ## Listen to scroll changes Listen to the vertical and horizontal scroll changes by using the [verticalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/verticalScrollController.html) and [horizontalScrollController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/horizontalScrollController.html) properties respectively. Set listeners on these controllers using the `addListener` method to receive notifications when scrolling occurs. -> **NOTE:** The `intl` package is required for number formatting. Add `intl: ^0.19.0` to your `pubspec.yaml` dependencies. +> **Note:** The `intl` package is required for number formatting. Add `intl: ^0.19.0` to your `pubspec.yaml` dependencies. The following example demonstrates how to load more rows when vertical scrolling reaches 70% of the maximum scroll extent: @@ -726,16 +726,6 @@ class _EmployeeDataSource extends DataGridSource { ]); } - final List names = [ - 'Maria Anders', 'Francisco Chang', 'Roland Mendel', 'Yvonne Moncada', - 'Dominique Perrier', 'Fran Wilson', 'Giovanni Rovelli', 'Catherine Dewey' - ]; - - final List cities = [ - 'New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix', - 'Philadelphia', 'San Antonio', 'San Diego', 'Dallas', 'San Jose' - ]; - void loadEmployees(int count) { final Random random = Random(); final int startIndex = employees.isNotEmpty ? employees.length : 0, @@ -764,7 +754,7 @@ class _EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -> **NOTE:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-data-lazily-when-scrolling-reaches-70-in-flutter-datatable-sfdatagrid). +> **Note:** Download the complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-load-data-lazily-when-scrolling-reaches-70-in-flutter-datatable-sfdatagrid). ## Increase row cache limit @@ -772,7 +762,7 @@ By default, rows are generated based on the viewport size, and these rows are re The `rowsCacheExtent` property creates additional rows internally alongside the visible rows allocated based on viewport size, increasing the number of rows available for reuse. -> **NOTE:** Increasing `rowsCacheExtent` improves visual consistency but may impact performance with large datasets. Use this property judiciously based on your application's performance requirements. +> **Note:** Increasing `rowsCacheExtent` improves visual consistency but may impact performance with large datasets. Use this property judiciously based on your application's performance requirements. {% tabs %} {% highlight Dart %} @@ -838,7 +828,7 @@ The `rowsCacheExtent` property creates additional rows internally alongside the If the height or width of the DataGrid is infinity, then DataGrid sets its height or width to 300 by default. Users can set the height or width based on the number of rows or columns available in DataGrid by using the [shrinkWrapRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/shrinkWrapRows.html) or [shrinkWrapColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/shrinkWrapColumns.html) property, respectively. -> **NOTE:** Shrink wrapping is significantly more expensive than setting the height and width manually. Use this property only when the number of rows and columns is small. +> **Note:** Shrink wrapping is significantly more expensive than setting the height and width manually. Use this property only when the number of rows and columns is small. {% tabs %} {% highlight Dart %} @@ -975,7 +965,7 @@ In the SfDataGrid, you can obtain the starting and ending indices of the visible SfDataGrid allows you to set the scroll offset upon initial loading for both horizontal and vertical scrollbars. This is achieved by assigning the offset value to the [initialScrollOffset](https://api.flutter.dev/flutter/widgets/ScrollController/initialScrollOffset.html) property of the [ScrollController](https://api.flutter.dev/flutter/widgets/ScrollController-class.html) for the required vertical or horizontal controller. -> **NOTE:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` +> **Note:** Ensure you have imported the required package: `import 'package:syncfusion_flutter_datagrid/datagrid.dart';` {% tabs %} {% highlight Dart %} From 396daf2554b284828eed29c2f5c3be49fbd4d2ff Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 16:04:54 +0530 Subject: [PATCH 12/18] FLUT-1038842-[others][flutter]: UG Partial fixed --- Flutter/datagrid/export-to-excel.md | 202 ++++++++++++---------- Flutter/datagrid/export-to-pdf.md | 235 +++++++++++++------------- Flutter/datagrid/paging.md | 251 ++++++++++++++++------------ 3 files changed, 367 insertions(+), 321 deletions(-) diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index 25ddbb93d..e5176a506 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -19,14 +19,14 @@ The following dependencies must be added to your pubspec.yaml file for exporting dependencies: -syncfusion_flutter_datagrid: ^xx.x.xx -syncfusion_flutter_datagrid_export: ^xx.x.xx +syncfusion_flutter_datagrid_export: ^24.1.41 +syncfusion_flutter_xlsio: ^24.1.41 {% endhighlight %} -> **Note:** Replace **xx.x.xx** with the latest version of the packages from [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export). Ensure all three packages have compatible versions. Requires Flutter 3.0 and above. +> **Note:** The version numbers shown above are examples. Refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export) for the latest stable version of `Syncfusion Flutter DataGrid Export` and [xlsio](https://pub.dev/packages/syncfusion_flutter_xlsio) packages. -**Import package** +**Import required packages** Import the following packages in your Dart code. @@ -39,16 +39,19 @@ import 'package:syncfusion_flutter_xlsio/xlsio.dart'; {% endhighlight %} {% endtabs %} -Export the `SfDataGrid` by using the following extension methods present in the [SfDataGridState](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html) class. +Export SfDataGrid by using the following extension methods present in the [SfDataGridState](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html) class: -* [exportToExcelWorkbook](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorkbook.html) -* [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) +* [exportToExcelWorkbook](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorkbook.html) - Exports the grid to an Excel workbook +* [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) - Exports the grid to an existing Excel worksheet -> **Note:** You need to add the `path_provider` and `open_file` packages to your pubspec.yaml to use the helper method above. +> **Note:** +>- File export requires platform-specific permissions. Ensure write permissions are configured in AndroidManifest.xml (Android), Info.plist (iOS), and Entitlements (macOS). +>- For web platforms, use web APIs instead of the `File` class. Consider using the `universal_html` package or browser download methods. +>- Refer to [getting-started](https://help.syncfusion.com/flutter/xlsio/getting-started) for platform-specific file generation code. -**Add GlobalKey for the DataGrid** +**Add GlobalKey for SfDataGrid** -Create the [GlobalKey](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) using the `SfDataGridState` class. Exporting related methods are available in the [SfDataGridState](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGridState-class.html) class. +Create the [GlobalKey](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) using the `SfDataGridState` class. Exporting related methods are available in the `SfDataGridState` class. Set the created `GlobalKey` to the `SfDataGrid`. @@ -65,7 +68,7 @@ The following code illustrates how to create and export a `SfDataGrid` to Excel {% tabs %} {% highlight Dart %} -final GlobalKey _dataGridKey = GlobalKey(); +final GlobalKey key = GlobalKey(); @override Widget build(BuildContext context) { @@ -92,15 +95,15 @@ Widget build(BuildContext context) { )), onPressed: () async { final Workbook workbook = - _dataGridKey.currentState!.exportToExcelWorkbook(); + key.currentState!.exportToExcelWorkbook(); final List bytes = workbook.saveAsStream(); workbook.dispose(); - await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); + await helper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); }), ), Expanded( child: SfDataGrid( - key: _dataGridKey, + key: key, source: employeeDataSource, columns: [ GridColumn( @@ -143,53 +146,58 @@ Widget build(BuildContext context) { {% endhighlight %} {% endtabs %} +## Save the Excel document as a file + +Include platform-specific code to save the Excel document. Refer to the following sections for implementation details: +* [Mobile (Android/iOS) file saving](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-mobile) +* [Web file saving](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-web) +* [Desktop (Windows/macOS/Linux) file saving](https://help.syncfusion.com/flutter/xlsio/getting-started#create-an-excel-document-in-desktop) ## Export DataGrid to Excel workbook -You can export the data to an [Excel Workbook](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Workbook-class.html) by using the [exportToExcelWorkbook](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorkbook.html) method from the `currentState` of the DataGrid. +Export data to an [Excel Workbook](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Workbook-class.html) using the `exportToExcelWorkbook` method from the DataGrid's state. This creates a new workbook with the grid data. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook(); +final Workbook workbook = key.currentState!.exportToExcelWorkbook(); final List bytes = workbook.saveAsStream(); -workbook.dispose(); -await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); +File('DataGrid.xlsx').writeAsBytes(bytes, flush: true); {% endhighlight %} {% endtabs %} ## Export DataGrid to Excel sheet -Export the data to an [Excel Worksheet](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Worksheet-class.html) by using the [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) method from the `currentState` of the DataGrid. +Export data to an [Excel Worksheet](https://pub.dev/documentation/syncfusion_flutter_xlsio/latest/xlsio/Worksheet-class.html) using the `exportToExcelWorksheet` method. This appends grid data to an existing or new worksheet within a workbook. {% tabs %} {% highlight Dart %} final Workbook workbook = Workbook(); final Worksheet worksheet = workbook.worksheets[0]; -_dataGridKey.currentState!.exportToExcelWorksheet(worksheet); +key.currentState!.exportToExcelWorksheet(worksheet); final List bytes = workbook.saveAsStream(); -workbook.dispose(); -await FileHelper.saveAndLaunchFile(bytes, 'DataGrid.xlsx'); +File('DataGrid.xlsx').writeAsBytes(bytes, flush: true); {% endhighlight %} {% endtabs %} -## Exporting options +## Exporting options + +> **Note:** Export methods use XLSX format by default. Large datasets may consume significant memory during export—consider exporting selected rows for better performance with large grids. ### Exclude columns when exporting -By default, all the columns in the `SfDataGrid` are exported to Excel. To exclude certain columns when exporting to Excel, add those column names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/excludeColumns.html) parameter. +By default, all columns in SfDataGrid are exported to Excel. Exclude specific columns by adding their names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/excludeColumns.html) parameter. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState! +Workbook workbook = key.currentState! .exportToExcelWorkbook(excludeColumns: ['Name']); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -198,109 +206,94 @@ workbook.dispose(); ### Exclude table summaries when exporting -By default, table summaries in the `SfDataGrid` are exported to Excel. Set the [exportTableSummaries](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportTableSummaries.html) parameter as `false` to export the `SfDataGrid` without table summaries. +By default, table summaries in SfDataGrid are exported to Excel. Set the [exportTableSummaries](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportTableSummaries.html) parameter to `false` to exclude table summaries from the export. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState! +Workbook workbook = key.currentState! .exportToExcelWorkbook(exportTableSummaries: false); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} ### Exclude stacked headers when exporting -By default, stacked headers in the `SfDataGrid` are exported to Excel. Set the [exportStackedHeaders](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportStackedHeaders.html) parameter as `false` to export the `SfDataGrid` without stacked headers. +By default, stacked headers in SfDataGrid are exported to Excel. Set the [exportStackedHeaders](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportStackedHeaders.html) parameter to `false` to exclude stacked headers from the export. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState! +Workbook workbook = key.currentState! .exportToExcelWorkbook(exportStackedHeaders: false); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} ### Change the start row and column index when exporting -By default, the DataGrid is exported from the (0,0) index in an Excel sheet. Export the data from a specific row and column indexes in an Excel worksheet by setting the [startColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/startColumnIndex.html) and [startRowIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/startRowIndex.html) properties. +By default, the DataGrid is exported starting at cell (0,0) in the Excel sheet. Export data starting from a specific row and column by setting the [startRowIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/startRowIndex.html) and [startColumnIndex](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/startColumnIndex.html) properties. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState! +Workbook workbook = key.currentState! .exportToExcelWorkbook(startRowIndex: 3, startColumnIndex: 2); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} ## Export the selected rows to Excel -By default, the entire grid is exported to Excel. Export the selected rows only by passing the [selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) from the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) to the [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToExcelWorksheet` and `exportToExcelWorkbook` methods. +By default, the entire grid is exported to Excel. Export only selected rows by passing the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) list to the `rows` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` methods. This parameter is optional; if omitted, all rows are exported. {% tabs %} {% highlight Dart %} -final DataGridController controller = DataGridController(); - -// In your SfDataGrid widget -SfDataGrid( - controller: controller, - // ... other properties -); - -// Export selected rows -final Workbook workbook = _dataGridKey.currentState! - .exportToExcelWorkbook(rows: controller.selectedRows); +Workbook workbook = key.currentState! + .exportToExcelWorkbook(rows: dataGridController.selectedRows); final List bytes = workbook.saveAsStream(); -workbook.dispose(); -await FileHelper.saveAndLaunchFile(bytes, 'SelectedRows.xlsx'); {% endhighlight %} {% endtabs %} -> **Note:** Ensure row selection is enabled in the SfDataGrid by setting the `selectionMode` property to `SelectionMode.multiple` or `SelectionMode.single`. - ## Row height and column width customization -The following table explains how row height and column width are handled during export: +By default, the exported Excel cells use the [rowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowHeight.html) and [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/defaultColumnWidth.html) properties from SfDataGrid. -| Property | When `true` | When `false` | -|----------|-----------|-----------| -| [exportRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportRowHeight.html) | Uses `SfDataGrid.headerRowHeight` and `SfDataGrid.rowHeight` from the DataGrid | Uses [defaultRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultRowHeight.html) value | -| [exportColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportColumnWidth.html) | Uses actual column widths from the DataGrid | Uses [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultColumnWidth.html) value | +To use custom dimensions instead, set the [exportRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportRowHeight.html) and [exportColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/exportColumnWidth.html) properties to `false`, then specify [defaultRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultRowHeight.html) and [defaultColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/defaultColumnWidth.html). -**Example: Use custom row height and column width** +When `exportRowHeight` and `exportColumnWidth` are `true`, the grid's [headerRowHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/headerRowHeight.html), `rowHeight`, and actual column widths are exported to Excel. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( +Workbook workbook = key.currentState!.exportToExcelWorkbook( exportRowHeight: false, exportColumnWidth: false, defaultRowHeight: 35, defaultColumnWidth: 120); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} ## Styling cells based on the cell type in Excel -Customize the cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback parameter in the `exportToExcelWorkbook` and `exportToExcelWorksheet` methods. +Customize cell styles during export using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback parameter in the `exportToExcelWorkbook` or `exportToExcelWorksheet` methods. The callback provides access to [DataGridCellExcelExportDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails-class.html) with cell type information: + +* `DataGridExportCellType.columnHeader` - Header cells +* `DataGridExportCellType.stackedHeaderCell` - Stacked header cells +* `DataGridExportCellType.row` - Data row cells +* `DataGridExportCellType.tableSummaryRow` - Summary row cells {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( +final Workbook workbook = key.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.columnHeader) { details.excelRange.cellStyle.backColor = '#42A5F5'; @@ -309,7 +302,6 @@ final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} @@ -320,12 +312,12 @@ workbook.dispose(); ### Customize cell values while exporting -The cell value can be customized while exporting to Excel by directly setting the cell value to the [excelRange.value](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails/excelRange.html) property available in the argument of the `cellExport` callback. +Customize cell values during export by setting the [excelRange.value](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails/excelRange.html) property in the `cellExport` callback. The supported value types include strings, numbers, dates, and booleans. Complex types are converted to their string representation. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( +final Workbook workbook = key.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.row && details.cellValue == 'Project Lead') { @@ -333,21 +325,20 @@ final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} ![excel shows the cell customization](images/export-to-excel/flutter-datagrid-excel-export-cell-customization.png) -### Customize the cells based on the column +### Customize cells based on the column -You can customize the column style based on the column name when exporting to Excel by using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback parameter. +Customize cell styling by column using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter/cellExport.html) callback. Access the column name via [details.columnName](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellExcelExportDetails/columnName.html) to apply styles to specific columns. {% tabs %} {% highlight Dart %} -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( +final Workbook workbook = key.currentState!.exportToExcelWorkbook( cellExport: (DataGridCellExcelExportDetails details) { if (details.cellType == DataGridExportCellType.row && details.columnName == 'Name') { @@ -357,61 +348,92 @@ final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook( } }); final List bytes = workbook.saveAsStream(); -workbook.dispose(); {% endhighlight %} {% endtabs %} -## Customize Exporting Behavior +## Customize Exporting Behavior -Customize the exporting behavior by overriding the available methods in the [DataGridToExcelConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter-class.html) class. Use the `converter` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` method. +Customize export behavior by extending the [DataGridToExcelConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToExcelConverter-class.html) class and overriding specific methods. Pass your custom converter to the `converter` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` method. -**Example: Customize column headers and apply formatting** +> **Note:** Use `getCellValue` to transform cell data before export. Override `exportColumnHeader`, `exportRow`, or other export methods for advanced customization of specific row/column types. {% tabs %} {% highlight Dart %} class CustomDataGridToExcelConverter extends DataGridToExcelConverter { + /// Customize export of individual column header cells + @override + void exportColumnHeader(SfDataGrid dataGrid, GridColumn column, + String columnName, Worksheet worksheet) { + super.exportColumnHeader(dataGrid, column, columnName, worksheet); + } + + /// Customize export of all column headers @override void exportColumnHeaders(SfDataGrid dataGrid, Worksheet worksheet) { - // Apply custom formatting to headers super.exportColumnHeaders(dataGrid, worksheet); - final Range headerRange = worksheet.getRangeByIndex(1, 1, 1, dataGrid.columns.length); - headerRange.cellStyle.bold = true; - headerRange.cellStyle.fontSize = 12; } + /// Customize export of individual row cells for each column @override - Object? getCellValue(DataGridRow row, GridColumn column) { - // Customize cell values during export - final Object? cellValue = super.getCellValue(row, column); - if (column.columnName == 'Salary' && cellValue != null) { - return '\$$cellValue'; // Format salary with currency symbol - } - return cellValue; + void exportRow(SfDataGrid dataGrid, DataGridRow row, GridColumn column, + Worksheet worksheet) { + super.exportRow(dataGrid, row, column, worksheet); + } + + /// Customize export of all data rows + @override + void exportRows( + SfDataGrid dataGrid, List rows, Worksheet worksheet) { + super.exportRows(dataGrid, rows, worksheet); } + /// Customize export of individual stacked header rows + @override + void exportStackedHeaderRow(SfDataGrid dataGrid, + StackedHeaderRow stackedHeaderRow, Worksheet worksheet) { + super.exportStackedHeaderRow(dataGrid, stackedHeaderRow, worksheet); + } + + /// Customize export of all stacked header rows + @override + void exportStackedHeaderRows(SfDataGrid dataGrid, Worksheet worksheet) { + super.exportStackedHeaderRows(dataGrid, worksheet); + } + + /// Customize export of individual table summary rows + @override + void exportTableSummaryRow(SfDataGrid dataGrid, + GridTableSummaryRow summaryRow, Worksheet worksheet) { + super.exportTableSummaryRow(dataGrid, summaryRow, worksheet); + } + + /// Customize export of all table summary rows at specified positions @override void exportTableSummaryRows(SfDataGrid dataGrid, GridTableSummaryRowPosition position, Worksheet worksheet) { - // Add custom handling for summary rows super.exportTableSummaryRows(dataGrid, position, worksheet); } + + /// Transform cell values before export (e.g., formatting, type conversion) + @override + Object? getCellValue(DataGridRow row, GridColumn column) { + return super.getCellValue(row, column); + } } {% endhighlight %} {% endtabs %} -**Use the custom converter when exporting** +The following code sample illustrates how to create an instance of the `CustomDataGridToExcelConverter` class and set the instance to the `converter` parameter in the `exportToExcelWorksheet` or `exportToExcelWorkbook` method. {% tabs %} {% highlight Dart %} -final CustomDataGridToExcelConverter converter = CustomDataGridToExcelConverter(); -final Workbook workbook = _dataGridKey.currentState!.exportToExcelWorkbook(converter: converter); +CustomDataGridToExcelConverter converter = CustomDataGridToExcelConverter(); +Workbook workbook = key.currentState!.exportToExcelWorkbook(converter: converter); final List bytes = workbook.saveAsStream(); -workbook.dispose(); -await FileHelper.saveAndLaunchFile(bytes, 'CustomExport.xlsx'); {% endhighlight %} -{% endtabs %} +{% endtabs %} \ No newline at end of file diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index d19b9b723..906421a38 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -18,12 +18,14 @@ The following dependencies must be added to your `pubspec.yaml` file for exporti {% highlight dart %} dependencies: - syncfusion_flutter_datagrid_export: ^24.1.41 - syncfusion_flutter_pdf: ^24.1.41 + +syncfusion_flutter_datagrid_export: ^xx.x.xx {% endhighlight %} ->**NOTE** Ensure that you have the latest version of the `syncfusion_flutter_datagrid_export` and `syncfusion_flutter_pdf` packages. For the latest available versions, refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export). +> **Note:** +>- Here, **xx.x.xx** denotes the current version of `Syncfusion® Flutter DataGrid Export` package. Find the latest version on [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export). +>- Supported on Android, iOS, web, macOS, and Windows platforms. **Import package** @@ -33,7 +35,9 @@ Import the following packages in your Dart code. {% highlight Dart %} import 'dart:io'; + import 'package:syncfusion_flutter_datagrid_export/export.dart'; + import 'package:syncfusion_flutter_pdf/pdf.dart'; {% endhighlight %} @@ -49,102 +53,99 @@ You can export the `SfDataGrid` to PDF by using the following extension methods Create a [GlobalKey](https://api.flutter.dev/flutter/widgets/GlobalKey-class.html) using the `SfDataGridState` class. Exporting related methods are available via `SfDataGridState` class. +> **Note:** The GlobalKey must be assigned to the SfDataGrid widget to access export functionality. Without it, the export methods will not be available. + Set the created `GlobalKey` to the `SfDataGrid`. {% tabs %} {% highlight Dart %} -final GlobalKey key = GlobalKey(); + final GlobalKey key = GlobalKey(); {% endhighlight %} {% endtabs %} ->**NOTE** The `_employeeDataSource` used in the examples should be a [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) implementation containing your data model. Ensure that your data model includes properties like 'ID', 'Name', 'Designation', and 'Salary' as shown in the columns. - The following code illustrates how to create and display a `SfDataGrid` using the global key. {% tabs %} {% highlight Dart %} -GlobalKey key = GlobalKey(); - -@override -Widget build(BuildContext context) { - return Scaffold( - body: Column( - children: [ - ElevatedButton( - child: Text('Export To PDF'), - onPressed: () { - PdfDocument document = key.currentState!.exportToPdfDocument(); - final List bytes = document.saveSync(); - File('DataGrid.pdf').writeAsBytes(bytes); - }), - Expanded( - child: SfDataGrid( - key: key, - source: _employeeDataSource, - columns: [ - GridColumn( - columnName: 'ID', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'ID', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Name', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Name', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Designation', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Designation', - overflow: TextOverflow.ellipsis, - ))), - GridColumn( - columnName: 'Salary', - label: Container( - padding: EdgeInsets.symmetric(horizontal: 16.0), - alignment: Alignment.center, - child: Text( - 'Salary', - overflow: TextOverflow.ellipsis, - ))), - ], + GlobalKey key = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + ElevatedButton( + child: Text('Export To Pdf'), + onPressed: () { + PdfDocument document = key.currentState!.exportToPdfDocument() + final List bytes = document.saveSync(); + }), + Expanded( + child: SfDataGrid( + source: _employeeDataSource, + columns: [ + GridColumn( + columnName: 'ID', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'ID', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Name', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Name', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Designation', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Designation', + overflow: TextOverflow.ellipsis, + ))), + GridColumn( + columnName: 'Salary', + label: Container( + padding: EdgeInsets.symmetric(horizontal: 16.0), + alignment: Alignment.center, + child: Text( + 'Salary', + overflow: TextOverflow.ellipsis, + ))), + ], + ), ), - ), - ], - ), - ); -} + ], + ), + ); + } {% endhighlight %} {% endtabs %} ## Save the PDF document as a file -To save the exported PDF file, include platform-specific file generating code based on your target platform: +To save the file as a PDF document, platform-specific code is required based on the target platform: -- **Mobile (iOS/Android)**: Refer to [Save and open a PDF document in mobile](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) -- **Web**: Refer to [Save and download a PDF document in web](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) -- **Desktop (Windows/macOS/Linux)**: Use the `File` class from the `dart:io` package to write bytes to a file - ->**NOTE** The `File` class requires the `dart:io` package, which is already included in your imports from the previous section. +> **Note:** See the following documentation for platform-specific file saving implementations: +>- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) +>- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) +>- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/flutter/pdf/getting-started#save-a-pdf-document-in-desktop) ## Export DataGrid to PDF document -Use the [exportToPdfDocument](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfDocument.html) method to export the data to a [PdfDocument](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocument-class.html). +Export the data to the [PdfDocument](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocument-class.html) by using the `exportToPdfDocument` method from the `key.currentState` of the DataGrid. {% tabs %} {% highlight Dart %} @@ -158,9 +159,7 @@ File('DataGrid.pdf').writeAsBytes(bytes); ## Export DataGrid to PDF Grid -Use the [exportToPdfGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridPdfExportExtensions/exportToPdfGrid.html) method to export the data to a [PdfGrid](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfGrid-class.html). This method is useful when you need more control over page settings or when combining the grid with other content. - ->**NOTE** The `exportToPdfGrid` method returns a `PdfGrid` that can be drawn onto a `PdfPage`, allowing for customization of page orientation, margins, and other page-level settings. +Export the data to the [PdfGrid](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfGrid-class.html) by using the `exportToPdfGrid` method from the `key.currentState` of the DataGrid. {% tabs %} {% highlight Dart %} @@ -178,26 +177,11 @@ File('DataGrid.pdf').writeAsBytes(bytes); {% endhighlight %} {% endtabs %} -## Exporting options - -The following table summarizes the available export options and their use cases: - -| Parameter | Type | Default | Description | -|-----------|------|---------|-------------| -| `excludeColumns` | List | - | Columns to exclude from the export | -| `canRepeatHeaders` | bool | true | Repeat column headers on each page | -| `fitAllColumnsInOnePage` | bool | false | Fit all columns on a single page | -| `exportTableSummaries` | bool | true | Include table summaries in export | -| `exportStackedHeaders` | bool | true | Include stacked headers in export | -| `autoColumnWidth` | bool | true | Automatically size column widths | -| `rows` | List | null | Specific rows to export (null = all rows) | -| `cellExport` | Function | null | Callback for cell customization | -| `headerFooterExport` | Function | null | Callback for header/footer customization | -| `converter` | DataGridToPdfConverter | null | Custom converter class for advanced customization | +## Exporting options ### Exclude columns when exporting -By default, all columns in the SfDataGrid are exported to PDF. To exclude specific columns, add the column names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/excludeColumns.html) parameter. +By default, all the columns in the `SfDataGrid` are exported to PDF. To exclude some particular columns while exporting to PDF, add those column names to the [excludeColumns](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/excludeColumns.html) parameter of the `exportToPdfDocument` or `exportToPdfGrid` method. {% tabs %} {% highlight Dart %} @@ -225,7 +209,7 @@ final List bytes = document.saveSync(); ### Export all columns on one page -Fit all columns on a single page by setting the [fitAllColumnsInOnePage](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/fitAllColumnsInOnePage.html) parameter to `true`. +Fit all the columns on one page by setting the [fitAllColumnsInOnePage](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/fitAllColumnsInOnePage.html) parameter as `true`. {% tabs %} {% highlight Dart %} @@ -236,9 +220,11 @@ final List bytes = document.saveSync(); {% endhighlight %} {% endtabs %} +> **Note:** When `fitAllColumnsInOnePage` is enabled, it takes priority over `autoColumnWidth`. If you need to use actual column widths, ensure `fitAllColumnsInOnePage` is `false`. + ### Exclude table summaries when exporting -By default, table summaries in `SfDataGrid` are exported to PDF. Set the [exportTableSummaries](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/exportTableSummaries.html) parameter as `false` to export the `SfDataGrid` without table summaries. +By default, table summaries in `SfDataGrid` are exported to PDF. Set the [exportTableSummaries](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/exportTableSummaries.html) parameter as `false` to export the `SfDataGrid` without table summaries (if applicable to your data source). {% tabs %} {% highlight Dart %} @@ -252,7 +238,7 @@ final List bytes = document.saveSync(); ### Exclude stacked headers when exporting -By default, stacked headers in `SfDataGrid` are exported to PDF. Set the [exportStackedHeaders](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/exportStackedHeaders.html) parameter as `false` to export the `SfDataGrid` without stacked headers. +By default, stacked headers in `SfDataGrid` are exported to PDF. Set the [exportStackedHeaders](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/exportStackedHeaders.html) parameter as `false` to export the `SfDataGrid` without stacked headers (if applicable to your data source). {% tabs %} {% highlight Dart %} @@ -265,23 +251,23 @@ final List bytes = document.saveSync(); ### Auto-size column widths in PDF -To export the actual column width from `SfDataGrid` instead of auto-sizing, set the [autoColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/autoColumnWidth.html) parameter to `false`. +In order to export the actual column width from `SfDataGrid` instead of the auto column width, set the [autoColumnWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/autoColumnWidth.html) parameter as `false`. {% tabs %} {% highlight Dart %} -PdfDocument document = key.currentState!.exportToPdfDocument(autoColumnWidth: false); +PdfDocument document = key.currentState!.exportToPdfDocument(autoColumnWidth: false, fitAllColumnsInOnePage: false); final List bytes = document.saveSync(); {% endhighlight %} {% endtabs %} ->**NOTE** If you disable `autoColumnWidth`, you must set `fitAllColumnsInOnePage` to `false`. In this configuration, overflowing columns will be drawn on the next page. The `fitAllColumnsInOnePage` parameter takes precedence over `autoColumnWidth`. +> **Note:** If you disable `autoColumnWidth`, you must also set `fitAllColumnsInOnePage` as `false` to allow overflowing columns to be drawn on subsequent pages. ## Change the orientation of the PDF document -Change the orientation of a page in a PDF document by using the [PdfDocument.pageSettings.orientation](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfPageSettings/orientation.html) property. +Change the orientation of a page in a PDF document by using the [PdfPageSettings.orientation](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfPageSettings/orientation.html) property. To change the page orientation, you need to export the `SfDataGrid` to `PdfGrid` using the `exportToPdfGrid` method and draw the exported `PdfGrid` into a `PdfDocument`. @@ -302,14 +288,14 @@ final List bytes = document.saveSync(); ## Export the selected rows to PDF -By default, the entire grid is exported to PDF. To export only selected rows, pass the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) to the [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. +By default, the entire grid is exported to PDF. Export the selected rows only by passing the [dataGridController.selectedRows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController/selectedRows.html) collection to the [rows](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/rows.html) parameter in `exportToPdfDocument` and `exportToPdfGrid` methods. ->**NOTE** Ensure that the [DataGridController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridController-class.html) is assigned to the SfDataGrid using the `controller` property and that row selection is enabled by setting `selectionMode` to an appropriate value (e.g., `SelectionMode.single` or `SelectionMode.multiple`). +> **Note:** If no rows are selected, the entire grid will be exported. Ensure rows are selected before calling the export method if you only want selected data. {% tabs %} {% highlight Dart %} -PdfDocument document = key.currentState!.exportToPdfDocument(rows: dataGridController.selectedRows); +PdfDocument document = key.currentState!.exportToPdfDocument(rows: dataGridController.selectedRows,); final List bytes = document.saveSync(); {% endhighlight %} @@ -321,6 +307,8 @@ final List bytes = document.saveSync(); Setting the [PdfPageTemplateElement](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfPageTemplateElement-class.html) to [headerFooterExport.pdfDocumentTemplate.top](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocumentTemplate/top.html) loads the content at the top of the page, while setting the `PdfPageTemplateElement` to [headerFooterExport.pdfDocumentTemplate.bottom](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocumentTemplate/bottom.html) loads the content at the bottom of the page. +> **Note:** Headers and footers defined via templates will be repeated on every page of the multi-page PDF document. + {% tabs %} {% highlight Dart %} @@ -346,7 +334,9 @@ final List bytes = document.saveSync(); ## Styling cells based on the cell type in PDF -Customize cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/cellExport.html) callback parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. The [DataGridExportCellType](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExportCellType.html) enum provides the following cell types: `columnHeader`, `row`, `stackedHeaderRow`, and `tableSummaryRow`. +You can customize the cell styles based on cell type using the [cellExport](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter/cellExport.html) parameter, which is a callback function in `exportToPdfDocument` or `exportToPdfGrid` methods. This callback is invoked for each cell during export, allowing you to modify styles and values dynamically. + +> **Note:** When both cell value and cell style properties are modified in the `cellExport` callback, both modifications are applied to the exported PDF cell. {% tabs %} {% highlight Dart %} @@ -354,12 +344,9 @@ Customize cell styles based on cell type using the [cellExport](https://pub.dev/ PdfDocument document = key.currentState!.exportToPdfDocument(cellExport: (details) { if (details.cellType == DataGridExportCellType.columnHeader) { details.pdfCell.style.backgroundBrush = PdfBrushes.pink; - } else if (details.cellType == DataGridExportCellType.row) { + } + if (details.cellType == DataGridExportCellType.row) { details.pdfCell.style.backgroundBrush = PdfBrushes.lightCyan; - } else if (details.cellType == DataGridExportCellType.stackedHeaderRow) { - details.pdfCell.style.backgroundBrush = PdfBrushes.lightGray; - } else if (details.cellType == DataGridExportCellType.tableSummaryRow) { - details.pdfCell.style.backgroundBrush = PdfBrushes.wheat; } }); final List bytes = document.saveSync(); @@ -373,7 +360,7 @@ final List bytes = document.saveSync(); ### Customize cell values while exporting -Customize cell values during export by setting the [PdfCell](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails/pdfCell.html) value property in the `cellExport` callback. The [DataGridCellPdfExportDetails](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails-class.html) provides cell information including `cellValue`, `columnName`, and `rowIndex`. +The cell value can be customized while exporting to PDF by directly setting the cell value of a cell in the `PdfGrid` via the [PdfCell](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridCellPdfExportDetails/pdfCell.html) property available in the argument of the `cellExport` callback. {% tabs %} {% highlight Dart %} @@ -393,27 +380,29 @@ final List bytes = document.saveSync(); ![pdf document shows the cell customization](images/export-to-pdf/flutter-datagrid-pdf-cell-customization.png) -### Customize cells based on column name +### Customize the Cells based on Column Name -Customize cell styles based on the column name using the `cellExport` callback parameter. +You can customize the column style based on the column name while exporting to PDF by using the `cellExport` parameter. {% tabs %} {% highlight Dart %} PdfDocument document = key.currentState!.exportToPdfDocument(cellExport: (details) { - if (details.cellType == DataGridExportCellType.row && - details.columnName == 'Customer Name') { - details.pdfCell.style.textBrush = PdfBrushes.red; + if (details.cellType == DataGridExportCellType.row && details.columnName == 'Customer Name') { + details.pdfCell.style.textBrush = PdfBrushes.red; + } } -}); +); final List bytes = document.saveSync(); {% endhighlight %} {% endtabs %} -## Customize exporting behavior +## Customize Exporting Behavior + +For advanced export scenarios beyond the standard customization options, customize the exporting behavior by overriding the available methods in the [DataGridToPdfConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter-class.html) class. Use the `converter` parameter in the `exportToPdfDocument` or `exportToPdfGrid` method. -For advanced customization, override methods in the [DataGridToPdfConverter](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridToPdfConverter-class.html) class and use the `converter` parameter in `exportToPdfDocument` or `exportToPdfGrid` methods. This allows you to control how column headers, rows, and data are processed during export. +> **Note:** Use custom converters when you need to modify the export logic for column headers, rows, or data formatting beyond what the standard parameters provide. {% tabs %} {% highlight Dart %} @@ -422,27 +411,27 @@ class CustomDataGridToPdfConverter extends DataGridToPdfConverter { @override void exportColumnHeader(SfDataGrid dataGrid, GridColumn column, String columnName, PdfGrid pdfGrid) { - // Add custom column header export logic here + // Custom implementation for individual column header export super.exportColumnHeader(dataGrid, column, columnName, pdfGrid); } @override void exportColumnHeaders( SfDataGrid dataGrid, List columns, PdfGrid pdfGrid) { - // Add custom column headers export logic here + // Custom implementation for all column headers export super.exportColumnHeaders(dataGrid, columns, pdfGrid); } @override void exportRows( List columns, List rows, PdfGrid pdfGrid) { - // Add custom rows export logic here + // Custom implementation for exporting multiple rows super.exportRows(columns, rows, pdfGrid); } @override void exportRow(List columns, DataGridRow row, PdfGrid pdfGrid) { - // Add custom row export logic here + // Custom implementation for exporting individual row super.exportRow(columns, row, pdfGrid); } } diff --git a/Flutter/datagrid/paging.md b/Flutter/datagrid/paging.md index be4760884..59f05de34 100644 --- a/Flutter/datagrid/paging.md +++ b/Flutter/datagrid/paging.md @@ -9,23 +9,42 @@ documentation: ug # Paging in Flutter DataGrid (SfDataGrid) -The Datagrid interactively supports the manipulation of data using the [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) control. This provides support to load data in segments when dealing with large volumes of data. The `SfDataPager` can be placed above or under based on the requirement to easily manage data paging. +The SfDataGrid interactively supports the manipulation of data using the [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) control. This provides support to load data in segments when dealing with large volumes of data. The `SfDataPager` can be placed above or below the SfDataGrid based on your requirement to easily manage data paging. -The Datagrid performs paging of data using the `SfDataPager`. To enable paging, follow this procedure +The SfDataGrid performs paging of data using the `SfDataPager`. To enable paging, follow these steps * Create a new `SfDataPager` widget, and set the [SfDataGrid.DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) to the [SfDataPager.delegate](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/delegate.html) property. -* Set the number of pages required to be displayed in the data pager by setting the [SfDataPager.pageCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageCount.html) property. This is calculated as the total row count divided by rows per page, then rounded up. +* Set the number of pages required to be displayed in the data pager by setting the [SfDataPager.pageCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageCount.html) property to a `double` value. * Set the number of buttons that should be displayed in view by setting the [SfDataPager.visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html) property. -* Load the data for a specific page in the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method. This method returns a `Future` and is called when navigating between pages in the data pager. +* Load the data for a specific page in the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method. This method is called for every page navigation from the data pager. The method notifies listeners to refresh the UI. -> **Note:** The `SfDataPager.visibleItemsCount` property default value is 5. Also, ensure that the [syncfusion_flutter_datagrid](https://pub.dev/packages/syncfusion_flutter_datagrid) and [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) packages are added to your `pubspec.yaml` file. +> **Note:** +>- The `SfDataPager.visibleItemsCount` property default value is 5. +>- Required imports - Ensure you have imported `syncfusion_flutter_datagrid`, `syncfusion_flutter_core`, and any data model classes. The `DataGridSource` is an abstract class that you must extend with your custom implementation. -The following code example illustrates using the `SfDataPager` with the Datagrid control: +The following code example illustrates using the `SfDataPager` with the SfDataGrid control: {% tabs %} {% highlight Dart %} import 'package:intl/intl.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:syncfusion_flutter_core/theme.dart'; + +// Define OrderInfo model class +class OrderInfo { + OrderInfo({ + required this.orderID, + required this.customerID, + required this.orderDate, + required this.freight, + }); + + final int orderID; + final String customerID; + final DateTime orderDate; + final double freight; +} final int _rowsPerPage = 15; final double _dataPagerHeight = 60.0; @@ -45,7 +64,7 @@ import 'package:intl/intl.dart'; height: _dataPagerHeight, child: SfDataPager( delegate: _orderInfoDataSource, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, )) ]); @@ -98,7 +117,9 @@ import 'package:intl/intl.dart'; class OrderInfoDataSource extends DataGridSource { OrderInfoDataSource() { - _paginatedOrders = _orders.getRange(0, 19).toList(growable: false); + _paginatedOrders = _orders.isNotEmpty + ? _orders.getRange(0, _orders.length > _rowsPerPage ? _rowsPerPage : _orders.length).toList(growable: false) + : []; buildPaginatedDataGridRows(); } @@ -183,20 +204,59 @@ class OrderInfoDataSource extends DataGridSource { ![flutter datapager with datagrid](images/paging/flutter-datapager.png) +## Callbacks + +The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) provides the [onPageNavigationStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationStart.html) and [onPageNavigationEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationEnd.html) callbacks to listen to page navigation at the widget level. + +Typically, these callbacks are used to show and hide a loading indicator during page transitions. + +{% tabs %} +{% highlight Dart %} + + @override + Widget build(BuildContext context) { + return Scaffold(body: LayoutBuilder(builder: (context, constraints) { + return Row(children: [ + Column(children: [ + SizedBox( + height: constraints.maxHeight - 60, + width: constraints.maxWidth, + child: _buildDataGrid(constraints)), + Container( + height: 60, + width: constraints.maxWidth, + child: SfDataPager( + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), + direction: Axis.horizontal, + onPageNavigationStart: (int pageIndex) { + // Customize this callback when page navigation begins + }, + delegate: _orderInfoDataSource, + onPageNavigationEnd: (int pageIndex) { + // Customize this callback when page navigation completes + })) + ]) + ]); + })); + } + +{% endhighlight %} +{% endtabs %} + ## Asynchronous data loading -You can load the data asynchronously to the `SfDataPager` by overriding the `handlePageChange` method and await the method while loading the data. +You can load data asynchronously to the `SfDataPager` by overriding the [handlePageChange](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/handlePageChange.html) method and awaiting the data fetch operation. -The [onPageNavigationStart](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationStart.html) and [onPageNavigationEnd](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onPageNavigationEnd.html) callbacks can be used to show and hide the loading indicator when navigating between pages. +Use the `onPageNavigationStart` and `onPageNavigationEnd` callbacks to show and hide a loading indicator when navigating between pages. -In the following example, a 2000ms delay is used to simulate asynchronous data loading. Replace this with an actual API call or database query in your application. +In the below example, we simulate asynchronous data loading with a 2000ms delay and display the loading indicator during this time. {% tabs %} {% highlight Dart %} import 'package:intl/intl.dart'; - bool showLoadingIndicator = true; + bool showLoadingIndicator = false; @override Widget build(BuildContext context) { @@ -211,7 +271,7 @@ import 'package:intl/intl.dart'; height: 60, width: constraints.maxWidth, child: SfDataPager( - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, onPageNavigationStart: (int pageIndex) { setState(() { @@ -256,8 +316,9 @@ import 'package:intl/intl.dart'; class OrderInfoDataSource extends DataGridSource { OrderInfoDataSource() { - int endIndex = _orders.length < _rowsPerPage ? _orders.length : _rowsPerPage; - _paginatedOrders = _orders.getRange(0, endIndex).toList(growable: false); + _paginatedOrders = _orders.isNotEmpty + ? _orders.getRange(0, _orders.length > _rowsPerPage ? _rowsPerPage : _orders.length).toList(growable: false) + : []; buildPaginatedDataGridRows(); } @@ -314,7 +375,6 @@ class OrderInfoDataSource extends DataGridSource { int startIndex = newPageIndex * _rowsPerPage; int endIndex = startIndex + _rowsPerPage; if (startIndex < _orders.length && endIndex <= _orders.length) { - // Simulate asynchronous data loading (replace with actual API call) await Future.delayed(Duration(milliseconds: 2000)); _paginatedOrders = _orders.getRange(startIndex, endIndex).toList(growable: false); @@ -344,44 +404,46 @@ class OrderInfoDataSource extends DataGridSource { ![flutter datapager with asynchronous loading](images/paging/flutter-datapager-asynchronous-loading.gif) -> **Note:** Download demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-show-loading-indicator-on-loading-page-in-flutter-datatable). +> **Note:** Download a complete demo application from [GitHub](https://github.com/SyncfusionExamples/how-to-show-loading-indicator-on-loading-page-in-flutter-datatable). ## Programmatic page navigation -The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) provides the support to navigate between the pages programmatically using a [DataPagerController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController-class.html) with the following options. +The `SfDataPager` provides support to navigate between pages programmatically using a [DataPagerController](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController-class.html) with the following methods: -* [nextPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/nextPage.html) — Navigate to the next page -* [previousPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/previousPage.html) — Navigate to the previous page -* [lastPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/lastPage.html) — Navigate to the last page -* [firstPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/firstPage.html) — Navigate to the first page +* [nextPage()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/nextPage.html) - Navigate to the next page +* [previousPage()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/previousPage.html) - Navigate to the previous page +* [lastPage()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/lastPage.html) - Navigate to the last page +* [firstPage()](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataPagerController/firstPage.html) - Navigate to the first page -The following code example shows how to navigate the previous page programmatically: +The following code example shows how to navigate to the previous page programmatically: {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - late DataPagerController _controller; - late OrderInfoDataSource _orderInfoDataSource; @override void initState() { super.initState(); _controller = DataPagerController(); - _orderInfoDataSource = OrderInfoDataSource(); + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); } @override Widget build(BuildContext context) { return Scaffold(body: LayoutBuilder(builder: (context, constraint) { return Column(children: [ - ElevatedButton( + MaterialButton( onPressed: () { _controller.previousPage(); }, - child: const Text('Move to Previous Page'), + child: Text('Move to Previous Page'), ), SizedBox( height: constraint.maxHeight - 120, @@ -393,7 +455,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; alignment: Alignment.center, child: SfDataPager( delegate: _orderInfoDataSource, - initialPageIndex: 0, + initialPageIndex: 2, controller: _controller, pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, @@ -407,48 +469,25 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ## Show dropdown button to choose rows per page -Show the dropdown button option to select a different number of rows per page by defining the [onRowsPerPageChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onRowsPerPageChanged.html) callback. If it is null, no option will be provided to select a different number of rows per page. +Display a dropdown button option to select a different number of rows per page by defining the [onRowsPerPageChanged](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/onRowsPerPageChanged.html) callback. If it is null, no option will be provided to change the number of rows per page. -Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/availableRowsPerPage.html) property to define the list of numbers to be displayed in the drop-down. The default value of the `availableRowsPerPage` property is [10, 15, 20]. +Use the [availableRowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/availableRowsPerPage.html) property to define the list of row counts displayed in the dropdown. The default value is [10, 15, 20]. -> **Note:** You can view the dropdown button option by horizontally scrolling the DataPager. The dropdown button option is not supported if the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) is vertical. Also, only values that are present in the `availableRowsPerPage` list can be selected from the dropdown. +> **Note:** You can view the dropdown button by horizontally scrolling the SfDataPager. The dropdown button option is not supported when the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) property is set to vertical. {% tabs %} {% highlight Dart %} -import 'package:syncfusion_flutter_datagrid/datagrid.dart'; - -// Employee model class -class Employee { - Employee({ - required this.id, - required this.name, - required this.designation, - required this.salary, - }); - - final int id; - final String name; - final String designation; - final int salary; -} - int _rowsPerPage = 10; List employees = []; late EmployeeDataSource employeeDataSource; double datapagerHeight = 70.0; - - // Sample data generation - List getEmployeeData() { - return [ - Employee(id: 1001, name: 'James', designation: 'Project Lead', salary: 20000), - Employee(id: 1002, name: 'Kathryn', designation: 'Manager', salary: 30000), - Employee(id: 1003, name: 'Lara', designation: 'Developer', salary: 15000), - Employee(id: 1004, name: 'Michael', designation: 'Developer', salary: 15000), - Employee(id: 1005, name: 'Martin', designation: 'Developer', salary: 15000), - // Add more employee records as needed - ]; - } + final List _column = [ + GridColumn(columnName: 'id', label: Container(child: Text('ID'))), + GridColumn(columnName: 'name', label: Container(child: Text('Name'))), + GridColumn(columnName: 'designation', label: Container(child: Text('Designation'))), + GridColumn(columnName: 'salary', label: Container(child: Text('Salary'))), + ]; @override void initState() { @@ -482,18 +521,17 @@ class Employee { onRowsPerPageChanged: (int? rowsPerPage) { setState(() { _rowsPerPage = rowsPerPage!; - employeeDataSource.updateDataGriDataSource(); + employeeDataSource.updateDataGridDataSource(); }); }, - pageCount: - ((employees.length / _rowsPerPage).ceil()).toDouble(), + pageCount: ((employees.length / _rowsPerPage).ceil()).toDouble(), )), ], ); })); } - class EmployeeDataSource extends DataGridSource { +class EmployeeDataSource extends DataGridSource { /// Creates the employee data source class with required details. EmployeeDataSource({required List employeeData}) { _employeeData = employeeData; @@ -534,16 +572,16 @@ class Employee { @override Future handlePageChange(int oldPageIndex, int newPageIndex) { - final int _startIndex = newPageIndex * _rowsPerPage; - int _endIndex = _startIndex + _rowsPerPage; - if (_endIndex > _employeeData.length) { - _endIndex = _employeeData.length; + final int startIndex = newPageIndex * _rowsPerPage; + int endIndex = startIndex + _rowsPerPage; + if (endIndex > _employeeData.length) { + endIndex = _employeeData.length; } - /// Get a particular range from the sorted collection. - if (_startIndex < _employeeData.length && - _endIndex <= _employeeData.length) { - _paginatedRows = _employeeData.getRange(_startIndex, _endIndex).toList(); + // Get a particular range from the data collection. + if (startIndex < _employeeData.length && + endIndex <= _employeeData.length) { + _paginatedRows = _employeeData.getRange(startIndex, endIndex).toList(); } else { _paginatedRows = []; } @@ -552,10 +590,10 @@ class Employee { return Future.value(true); } - void updateDataGriDataSource() { + void updateDataGridDataSource() { notifyListeners(); } - } +} {% endhighlight %} {% endtabs %} @@ -563,12 +601,12 @@ class Employee { ## Orientation -The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) allows you to arrange the child elements either horizontally or vertically. This can be achieved by using the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) property, which accepts `Axis.horizontal` or `Axis.vertical`. +`SfDataPager` allows you to arrange the navigation and page buttons either horizontally or vertically by using the [direction](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/direction.html) property. The `direction` property accepts an `Axis` enum value.
Property Name
@@ -578,7 +616,7 @@ Description Axis.horizontal @@ -586,7 +624,7 @@ Default value. Arranges all the navigation buttons and numeric page buttons hori Axis.vertical
-Value +Value Description -Default value. Arranges all the navigation buttons and numeric page buttons horizontally.{{'![flutter datapager in horizontal direction](images/paging/flutter-datapager-direction-horizontal.png)'|markdownify}} +This is the default value. Arranges all navigation buttons and page number buttons horizontally.{{'![flutter datapager in horizontal direction](images/paging/flutter-datapager-direction-horizontal.png)'|markdownify}}
-Arranges all the navigation buttons and numeric page buttons vertically.{{'![flutter datapager in vertical direction](images/paging/flutter-datapager-direction-vertical.png)'|markdownify}} +Arranges all navigation buttons and page number buttons vertically.{{'![flutter datapager in vertical direction](images/paging/flutter-datapager-direction-vertical.png)'|markdownify}}
@@ -594,19 +632,11 @@ Arranges all the navigation buttons and numeric page buttons vertically.{{'![flu ## Appearance -The [SfDataPager](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) allows customizing the appearance using the [SfDataPagerThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerThemeData-class.html) in [SfDataPagerTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerTheme-class.html). The `SfDataPager` should be wrapped inside the `SfDataPagerTheme` widget. - -Import the following class from the [syncfusion_flutter_core](https://pub.dev/packages/syncfusion_flutter_core) package: - -{% tabs %} -{% highlight Dart %} - -import 'package:syncfusion_flutter_core/theme.dart'; +Customize the appearance of the SfDataPager using the [SfDataPagerThemeData](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerThemeData-class.html) class within the [SfDataPagerTheme](https://pub.dev/documentation/syncfusion_flutter_core/latest/theme/SfDataPagerTheme-class.html) widget. Wrap the `SfDataPager` inside `SfDataPagerTheme` and configure the theme data. -{% endhighlight %} -{% endtabs %} +> **Note:** Import the theming package: `import 'package:syncfusion_flutter_core/theme.dart';` -The following code example illustrates using `SfDataPagerThemeData` with the data pager control +The following code example illustrates customizing the SfDataPager appearance: {% tabs %} {% highlight Dart %} @@ -623,7 +653,7 @@ The following code example illustrates using `SfDataPagerThemeData` with the dat ), child: SfDataPager( delegate: _orderInfoDataSource, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, ), ), @@ -637,7 +667,7 @@ The following code example illustrates using `SfDataPagerThemeData` with the dat ### Set the padding between page items -The padding between the page items including navigation page items such as first, last, previous and next can be changed by using the [itemPadding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemPadding.html) property. +The spacing between page number buttons and navigation buttons (first, last, previous, next) can be changed using the [itemPadding](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemPadding.html) property. {% tabs %} {% highlight Dart %} @@ -659,11 +689,11 @@ The padding between the page items including navigation page items such as first {% endhighlight %} {% endtabs %} -**Note:** The default value of `SfDataPager.itemPadding` is `5.0`. +> **Note:** The default value of `SfDataPager.itemPadding` is 5.0. ### Set the height and width of the page items -The default width and height of the page items are 50 and 50, respectively. To change the size of page number items, use the [itemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemWidth.html) and [itemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemHeight.html) properties. To change the size of navigation items (first, last, previous, and next), use the [navigationItemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemHeight.html) and [navigationItemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemWidth.html) properties. +The default width and height of the page number buttons are 50 and 50, respectively. To customize the size of page number buttons, use the [itemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemWidth.html) and [itemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/itemHeight.html) properties. For customizing navigation button sizes (first, last, previous, next), use the [navigationItemHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemHeight.html) and [navigationItemWidth](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/navigationItemWidth.html) properties. {% tabs %} {% highlight Dart %} @@ -700,14 +730,14 @@ The default width and height of the page items are 50 and 50, respectively. To c ### Hide certain navigation page items -To hide certain navigation page items, use the following properties: +To hide specific navigation buttons, use the following properties: - * [firstPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/firstPageItemVisible.html) - * [lastPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/lastPageItemVisible.html) - * [nextPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/nextPageItemVisible.html) - * [previousPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/previousPageItemVisible.html) + * [firstPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/firstPageItemVisible.html) - Show/hide the first page button + * [lastPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/lastPageItemVisible.html) - Show/hide the last page button + * [nextPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/nextPageItemVisible.html) - Show/hide the next page button + * [previousPageItemVisible](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/previousPageItemVisible.html) - Show/hide the previous page button -**Note:** The default value of all these properties is `true`. + > **Note:** The default value for all these properties is `true`. {% tabs %} {% highlight Dart %} @@ -755,7 +785,7 @@ To hide certain navigation page items, use the following properties: ## Change the number of visible items (buttons) in the view -You can change the number of visible items i.e. page buttons in view by using the [SfDataPager.visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html). +You can control the number of page buttons displayed at once using the [visibleItemsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/visibleItemsCount.html) property. {% tabs %} {% highlight Dart %} @@ -778,7 +808,7 @@ You can change the number of visible items i.e. page buttons in view by using th child: SfDataPager( visibleItemsCount: 1, delegate: _orderInfoDataSource, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, ), ) @@ -792,7 +822,7 @@ You can change the number of visible items i.e. page buttons in view by using th ## Load any widget in the page button -Load any widget to the page button by using the [SfDataPager.pageItemBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageItemBuilder.html). +Customize the appearance of page buttons by providing a custom widget using the [pageItemBuilder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager/pageItemBuilder.html) callback. {% tabs %} {% highlight Dart %} @@ -828,7 +858,7 @@ Load any widget to the page button by using the [SfDataPager.pageItemBuilder](ht )); }, delegate: _orderInfoDataSource, - pageCount: _orders.length / _rowsPerPage, + pageCount: (_orders.length / _rowsPerPage).ceil().toDouble(), direction: Axis.horizontal, ))) ]); @@ -838,11 +868,13 @@ Load any widget to the page button by using the [SfDataPager.pageItemBuilder](ht {% endhighlight %} {% endtabs %} -## Sort all the rows instead of rows available on a page +## Alternative: Automatic pagination without manual handlePageChange -By default, when the `handlePageChange` method is overridden in the `DataGridSource` class, sorting is applied only to the rows available on the current page. To sort all rows available for paging, do not override the `handlePageChange` method. In this case, the DataGrid will automatically split the rows required for each page based on the `SfDataPager.pageCount` after sorting all rows. +By default, when you override the `handlePageChange` method, you manually manage which rows to display for each page. However, if you want automatic pagination where sorting and filtering apply to all rows before pagination, do not override the `handlePageChange` method in the `DataGridSource` class. -Alternatively, if you want to use automatic pagination with sorting, use the [SfDataGrid.rowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsPerPage.html) property instead of manually handling pagination. With this approach, do not override the `handlePageChange` method, and the DataGrid will manage pagination automatically while applying sorting to all rows. +When `handlePageChange` is not overridden, the SfDataGrid automatically splits the rows required for each page based on the `pageCount` property using the following formula: `pageCount = (total rows / rowsPerPage)`. + +Use the [rowsPerPage](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/rowsPerPage.html) property on the SfDataGrid to specify how many rows should appear per page. This approach ensures that operations like sorting apply to the entire dataset before pagination occurs. {% tabs %} {% highlight Dart %} @@ -969,6 +1001,9 @@ class OrderInfoDataSource extends DataGridSource { }).toList()); } + // Note: handlePageChange is NOT overridden in this example. + // The SfDataGrid automatically handles pagination and sorting. + void buildDataGridRows() { dataGridRows = _orders.map((dataGridRow) { return DataGridRow(cells: [ From 62a624ae99915c4f9e5fc01fce97c7e733e49dfa Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 16:53:46 +0530 Subject: [PATCH 13/18] FLUT-1038842-[others][flutter]: Review correction fixed --- Flutter/datagrid/accessibility.md | 19 ------------------- Flutter/datagrid/column-types.md | 2 -- Flutter/datagrid/conditional-styling.md | 2 -- Flutter/datagrid/data-binding.md | 2 +- Flutter/datagrid/editing.md | 6 ++---- Flutter/datagrid/export-to-excel.md | 5 ++--- Flutter/datagrid/export-to-pdf.md | 8 +++----- Flutter/datagrid/footer.md | 9 --------- Flutter/datagrid/grouping.md | 2 +- Flutter/datagrid/localization.md | 7 ------- Flutter/datagrid/overview.md | 2 -- Flutter/datagrid/placeholder.md | 15 --------------- 12 files changed, 9 insertions(+), 70 deletions(-) diff --git a/Flutter/datagrid/accessibility.md b/Flutter/datagrid/accessibility.md index e6f0c12f7..a5032e715 100644 --- a/Flutter/datagrid/accessibility.md +++ b/Flutter/datagrid/accessibility.md @@ -236,22 +236,3 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; {% endhighlight %} {% endtabs %} -## Testing accessibility - -To ensure your DataGrid implementation is accessible, follow these testing practices: - -* **Screen reader testing:** Use Android TalkBack or iOS VoiceOver to verify that cell content is properly announced. -* **Keyboard navigation:** Test all keyboard interactions on desktop platforms (Windows, macOS, Linux) to ensure proper navigation flow. -* **Color contrast:** Validate that all text meets WCAG 2.1 AA color contrast requirements (4.5:1 for normal text). -* **Text scaling:** Test your grid with text scale factors of 1.0x, 1.25x, 1.5x, and 2.0x to ensure content remains readable. -* **Automated testing:** Use accessibility scanning tools available in Android Studio and Xcode to detect potential accessibility issues. - -## Related resources - -For comprehensive information on implementing accessible DataGrid functionality, refer to the following resources: - -* [DataGrid selection guide](https://help.syncfusion.com/flutter/datagrid/selection) -* [DataGrid API documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/) -* [Flutter accessibility guide](https://flutter.dev/docs/development/accessibility-and-localization/accessibility) -* [WCAG 2.1 accessibility standards](https://www.w3.org/WAI/WCAG21/quickref/) - diff --git a/Flutter/datagrid/column-types.md b/Flutter/datagrid/column-types.md index 9262d8fb3..92b199a03 100644 --- a/Flutter/datagrid/column-types.md +++ b/Flutter/datagrid/column-types.md @@ -11,8 +11,6 @@ documentation: ug [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) provides support for loading any type of widget in each column. The `SfDataGrid` supports two main column types: `GridColumn` for standard data binding and a `Checkbox` column for row selection. This document covers the features and customization options available for each column type. -> **Note:** Ensure that you have added the `syncfusion_flutter_datagrid` package to your `pubspec.yaml` file. For more information, refer to the [getting started with Flutter DataGrid](getting-started.md) documentation. - ## GridColumn GridColumn is a class that provides base functionalities for all the column types in `SfDataGrid`. diff --git a/Flutter/datagrid/conditional-styling.md b/Flutter/datagrid/conditional-styling.md index 2018419cd..18498273d 100644 --- a/Flutter/datagrid/conditional-styling.md +++ b/Flutter/datagrid/conditional-styling.md @@ -11,8 +11,6 @@ documentation: ug The [SfDataGrid](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) allows customizing the style of individual cells and rows based on your requirements. You can customize your widget in the `DataGridSource.buildRow` method with the help of `DataGridRowAdapter`. -> **Note:** Ensure you have added the `syncfusion_flutter_datagrid` package to your project's `pubspec.yaml` file. Refer to the [getting-started](getting-started.md) guide for installation instructions. - ## Employee Model Class The following examples use an `Employee` model class. Define it as shown below: diff --git a/Flutter/datagrid/data-binding.md b/Flutter/datagrid/data-binding.md index 9d84da691..2ea9d6a25 100644 --- a/Flutter/datagrid/data-binding.md +++ b/Flutter/datagrid/data-binding.md @@ -1,7 +1,7 @@ --- layout: post title: Data Binding in Flutter DataGrid | DataTable | Syncfusion -description: Learn how to set the Data source for Syncfusion Flutter DataGrid (SfDataGrid) widget and more. +description: Learn how to configure and manage the data source for Syncfusion Flutter DataGrid (SfDataGrid) to display data efficiently. platform: flutter control: SfDataGrid documentation: ug diff --git a/Flutter/datagrid/editing.md b/Flutter/datagrid/editing.md index fcaadb675..61f0a210d 100644 --- a/Flutter/datagrid/editing.md +++ b/Flutter/datagrid/editing.md @@ -387,7 +387,7 @@ By default, a cell will enter edit mode when you double-tap it. To enable editin ## Methods -> **Note:** The editing lifecycle consists of three key methods: `onCellBeginEdit` (called when entering edit mode), `canSubmitCell` (called before exiting edit mode for validation), and `onCellSubmit` (called when changes are confirmed). All methods are asynchronous-capable. +> **Note:** The editing life cycle consists of three key methods: `onCellBeginEdit` (called when entering edit mode), `canSubmitCell` (called before exiting edit mode for validation), and `onCellSubmit` (called when changes are confirmed). All methods are asynchronous-capable. ### onCellBeginEdit @@ -501,7 +501,7 @@ class EmployeeDataSource extends DataGridSource { ### onCellCancelEdit -The [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) method is called when editing is cancelled. This occurs when the `Esc` key is pressed on Web and Desktop platforms. When this method is called, the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) and [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) methods are not called. Focus returns to the DataGrid after cancellation. +The [DataGridSource.onCellCancelEdit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellCancelEdit.html) method is called when editing is canceled. This occurs when the `Esc` key is pressed on Web and Desktop platforms. When this method is called, the [canSubmitCell](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/canSubmitCell.html) and [onCellSubmit](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource/onCellSubmit.html) methods are not called. Focus returns to the DataGrid after cancellation. > **Note:** You do not need to call `notifyListeners` inside this method as the UI automatically handles state updates. @@ -996,5 +996,3 @@ class _MyHomePageState extends State { {% endhighlight %} {% endtabs %} - -> **Note:** The `StreamController` pattern is used here to manage UI state during async operations. The loading indicator is shown/hidden by emitting values to the stream. You can also use state management solutions like `Provider`, `Riverpod`, or `Bloc` for more complex scenarios. diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index e5176a506..4a6dd2ed6 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -1,7 +1,7 @@ --- layout: post title: Export Flutter DataGrid to Excel | Flutter DataTable | Syncfusion -description: Learn how to export the Syncfusion Flutter DataGrid (SfDataGrid) into Excel and more. +description: Learn how to export the Syncfusion Flutter DataGrid (SfDataGrid) to Excel and easily customize the exported worksheets. platform: flutter control: SfDataGrid documentation: ug @@ -20,11 +20,10 @@ The following dependencies must be added to your pubspec.yaml file for exporting dependencies: syncfusion_flutter_datagrid_export: ^24.1.41 -syncfusion_flutter_xlsio: ^24.1.41 {% endhighlight %} -> **Note:** The version numbers shown above are examples. Refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export) for the latest stable version of `Syncfusion Flutter DataGrid Export` and [xlsio](https://pub.dev/packages/syncfusion_flutter_xlsio) packages. +> **Note:** The version numbers shown above are examples. Refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_datagrid_export) for the latest stable version of `Syncfusion Flutter DataGrid Export` package. **Import required packages** diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index 906421a38..540193d2c 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -34,8 +34,6 @@ Import the following packages in your Dart code. {% tabs %} {% highlight Dart %} -import 'dart:io'; - import 'package:syncfusion_flutter_datagrid_export/export.dart'; import 'package:syncfusion_flutter_pdf/pdf.dart'; @@ -139,9 +137,9 @@ The following code illustrates how to create and display a `SfDataGrid` using th To save the file as a PDF document, platform-specific code is required based on the target platform: > **Note:** See the following documentation for platform-specific file saving implementations: ->- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) ->- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) ->- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/flutter/pdf/getting-started#save-a-pdf-document-in-desktop) +>- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started/#save-and-open-a-pdf-document-in-mobile) +>- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started/#save-and-download-a-pdf-document-in-web) +>- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/flutter/pdf/getting-started/#save-a-pdf-document-in-desktop) ## Export DataGrid to PDF document diff --git a/Flutter/datagrid/footer.md b/Flutter/datagrid/footer.md index abc145d88..30525c6df 100644 --- a/Flutter/datagrid/footer.md +++ b/Flutter/datagrid/footer.md @@ -191,12 +191,3 @@ By default, the footer row is displayed below the last data row. To keep the foo {% endtabs %} ![flutter datagrid shows footer always on bottom](images/footer/flutter-datagrid-footer-on-bottom.gif) - -## API reference - -Refer to the following API documentation for footer-related properties: - -* [SfDataGrid.footer](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footer.html) — Sets the widget to display as the footer row. -* [SfDataGrid.footerHeight](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerHeight.html) — Sets the height of the footer row. Default value is 49.0. -* [SfDataGrid.footerFrozenRowsCount](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/footerFrozenRowsCount.html) — Sets the number of frozen footer rows. Set to 1 to keep the footer visible during vertical scrolling. -* [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — Base class for providing rows to SfDataGrid. diff --git a/Flutter/datagrid/grouping.md b/Flutter/datagrid/grouping.md index 47921589d..b5524e3f1 100644 --- a/Flutter/datagrid/grouping.md +++ b/Flutter/datagrid/grouping.md @@ -1,7 +1,7 @@ --- layout: post title: Grouping in Flutter DataGrid | DataTable | Syncfusion -description: Learn all about how to perform grouping and multi-grouping to the data source through column in the Syncfusion Flutter DataGrid (SfDataGrid) widget and more here. +description: Learn all about grouping and multi-grouping data through columns in the Syncfusion Flutter DataGrid (SfDataGrid) widget and more. platform: flutter control: SfDataGrid documentation: ug diff --git a/Flutter/datagrid/localization.md b/Flutter/datagrid/localization.md index 0bc5f668e..fabd0e3e5 100644 --- a/Flutter/datagrid/localization.md +++ b/Flutter/datagrid/localization.md @@ -402,10 +402,3 @@ class EmployeeDataSource extends DataGridSource { > **Note:** After adding the packages, hot reload or restart your app to apply the localization changes. Supported locales include Chinese (zh), Arabic (ar), Japanese (ja), Hindi (hi), French (fr), German (de), Spanish (es), Portuguese (pt), Russian (ru), and more. See [SfGlobalLocalizations](https://pub.dev/documentation/syncfusion_localizations/latest/syncfusion_localizations/SfGlobalLocalizations-class.html) for the complete list. flutter datagrid localization - -## See also - -* [SfDataGrid API Documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid-class.html) -* [SfDataPager API Documentation](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataPager-class.html) -* [Syncfusion Localizations Package](https://pub.dev/packages/syncfusion_localizations) -* [Flutter Localizations Documentation](https://api.flutter.dev/flutter/widgets/LocalizationsDelegate-class.html) diff --git a/Flutter/datagrid/overview.md b/Flutter/datagrid/overview.md index 5c0fe83bc..387528f0f 100644 --- a/Flutter/datagrid/overview.md +++ b/Flutter/datagrid/overview.md @@ -11,8 +11,6 @@ documentation: ug The Syncfusion® Flutter DataGrid is used to display and manipulate data in a tabular view. It is built from the ground up to achieve the best possible performance, even when loading large amounts of data. -> **Note:** The SfDataGrid widget is compatible with iOS, Android, Web, macOS, and Windows platforms. Ensure you have Flutter SDK 3.0 or later installed. For detailed setup instructions, refer to the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. - ![Overview Flutter Datagrid](images/overview/flutter-datagrid-overview.png) diff --git a/Flutter/datagrid/placeholder.md b/Flutter/datagrid/placeholder.md index b0c26daaa..c71ff15ad 100644 --- a/Flutter/datagrid/placeholder.md +++ b/Flutter/datagrid/placeholder.md @@ -84,19 +84,4 @@ The following example shows how to add a `placeholder` in SfDataGrid: Flutter DataGrid displays a placeholder when there are no rows -**Behavior** - -The placeholder widget is automatically displayed when: -- The data source is empty (contains no rows) -- The `SfDataGrid.placeholder` property is assigned - -The placeholder is automatically hidden when: -- Data is added to the data source -- Rows become available in the DataGrid - -**API Reference** - -* [SfDataGrid.placeholder](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/placeholder.html) — Gets or sets the widget to display when the DataGrid is empty. -* [DataGridSource](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/DataGridSource-class.html) — The data source for populating the DataGrid. - > **Sample application:** — Refer to the [DataGrid placeholder sample](https://support.syncfusion.com/kb/article/19825/how-to-show-an-empty-message-in-flutter-datatable) in the Syncfusion Flutter Examples repository for a complete working implementation. From 185302d84d11c1d30b584109e4afe7bde833f495 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 17:30:06 +0530 Subject: [PATCH 14/18] FLUT-1038842-[others][flutter]: Resolved CL failures --- Flutter/datagrid/columns-resizing.md | 2 +- Flutter/datagrid/editing.md | 2 +- Flutter/datagrid/export-to-excel.md | 2 +- Flutter/datagrid/export-to-pdf.md | 6 +++--- Flutter/datagrid/grouping.md | 2 +- Flutter/datagrid/right-to-left.md | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Flutter/datagrid/columns-resizing.md b/Flutter/datagrid/columns-resizing.md index 661c3c42c..5cd934b16 100644 --- a/Flutter/datagrid/columns-resizing.md +++ b/Flutter/datagrid/columns-resizing.md @@ -19,7 +19,7 @@ The column resizing indicator appears based on the platform. In web and desktop ## Basic Column Resizing -The following example demonstrates the basic column resizing setup. The `columnWidths` map stores the width of each column. Using `double.nan` as initial values allows the DataGrid to use default column width sizing until the user manually resizes a column. +The following example demonstrates the basic column resizing setup. The `columnWidths` map stores the width of each column. Initially, the `DataGrid` applies its default column sizing behavior, and the column widths are updated when the user manually resizes a column. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/editing.md b/Flutter/datagrid/editing.md index 61f0a210d..6e436c2d8 100644 --- a/Flutter/datagrid/editing.md +++ b/Flutter/datagrid/editing.md @@ -448,7 +448,7 @@ class EmployeeDataSource extends DataGridSource { {% endhighlight %} {% endtabs %} -> **Note:** To display validation error messages to users, consider showing a snackbar or dialog in the `canSubmitCell` method when returning `false`, or use a validation field overlay on the edit widget in `buildEditWidget`. +> **Note:** To display validation error messages to users, consider showing an error message dialog in the `canSubmitCell` method when returning `false`, or use a validation field overlay on the edit widget in `buildEditWidget`. ### onCellSubmit diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index 4a6dd2ed6..55f3851af 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -44,7 +44,7 @@ Export SfDataGrid by using the following extension methods present in the [SfDat * [exportToExcelWorksheet](https://pub.dev/documentation/syncfusion_flutter_datagrid_export/latest/syncfusion_flutter_datagrid_export/DataGridExcelExportExtensions/exportToExcelWorksheet.html) - Exports the grid to an existing Excel worksheet > **Note:** ->- File export requires platform-specific permissions. Ensure write permissions are configured in AndroidManifest.xml (Android), Info.plist (iOS), and Entitlements (macOS). +>- File export requires platform-specific permissions. Ensure write permissions are configured in AndroidManifest.xml (Android), the iOS app configuration file, and the macOS entitlements file. >- For web platforms, use web APIs instead of the `File` class. Consider using the `universal_html` package or browser download methods. >- Refer to [getting-started](https://help.syncfusion.com/flutter/xlsio/getting-started) for platform-specific file generation code. diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index 540193d2c..0b447051a 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -137,9 +137,9 @@ The following code illustrates how to create and display a `SfDataGrid` using th To save the file as a PDF document, platform-specific code is required based on the target platform: > **Note:** See the following documentation for platform-specific file saving implementations: ->- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started/#save-and-open-a-pdf-document-in-mobile) ->- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started/#save-and-download-a-pdf-document-in-web) ->- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/flutter/pdf/getting-started/#save-a-pdf-document-in-desktop) +>- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/#save-and-open-a-pdf-document-in-mobile) +>- [Web platform](https://help.syncfusion.com/#save-and-download-a-pdf-document-in-web) +>- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/#save-a-pdf-document-in-desktop) ## Export DataGrid to PDF document diff --git a/Flutter/datagrid/grouping.md b/Flutter/datagrid/grouping.md index b5524e3f1..f993154e0 100644 --- a/Flutter/datagrid/grouping.md +++ b/Flutter/datagrid/grouping.md @@ -799,7 +799,7 @@ When `allowExpandCollapseGroup` is set to `false`, groups are displayed but user ## Disable group expanding on the initial loading -By default, the SfDataGrid always expands all the groups. All the groups can be collapsed intially by setting the [SfDataGrid.autoExpandGroups](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/autoExpandGroups.html) property to false. +By default, the SfDataGrid always expands all the groups. All the groups can be collapsed initially by setting the [SfDataGrid.autoExpandGroups](https://pub.dev/documentation/syncfusion_flutter_datagrid/latest/datagrid/SfDataGrid/autoExpandGroups.html) property to false. {% tabs %} {% highlight Dart %} diff --git a/Flutter/datagrid/right-to-left.md b/Flutter/datagrid/right-to-left.md index 0f8349129..a9d2bd8bf 100644 --- a/Flutter/datagrid/right-to-left.md +++ b/Flutter/datagrid/right-to-left.md @@ -76,7 +76,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ### Changing the locale to RTL languages -Change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) property of [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html) to an RTL language such as Arabic (ar), Persian (fa), Hebrew (he), Pashto (ps), or Urdu (ur) to enable RTL rendering. +Change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) property of [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html) to an RTL language such as Arabic (`ar`), Persian (`fa`), Hebrew (`he`), Pashto (`ps`), or Urdu (`ur`) to enable RTL rendering. > **Note:** The `flutter_localizations` package is required. Add it to your `pubspec.yaml` file: > From 56bfeafe8f989451ac577a1b046930b28522994a Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 17:42:59 +0530 Subject: [PATCH 15/18] FLUT-1038842-[others][flutter]: CI Issue fixed --- Flutter/datagrid/export-to-excel.md | 1 - Flutter/datagrid/export-to-pdf.md | 4 ++-- Flutter/datagrid/overview.md | 1 - Flutter/datagrid/right-to-left.md | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Flutter/datagrid/export-to-excel.md b/Flutter/datagrid/export-to-excel.md index 55f3851af..4a88a0c1e 100644 --- a/Flutter/datagrid/export-to-excel.md +++ b/Flutter/datagrid/export-to-excel.md @@ -33,7 +33,6 @@ Import the following packages in your Dart code. {% highlight Dart %} import 'package:syncfusion_flutter_datagrid_export/export.dart'; -import 'package:syncfusion_flutter_xlsio/xlsio.dart'; {% endhighlight %} {% endtabs %} diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index 0b447051a..960b5f613 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -137,8 +137,8 @@ The following code illustrates how to create and display a `SfDataGrid` using th To save the file as a PDF document, platform-specific code is required based on the target platform: > **Note:** See the following documentation for platform-specific file saving implementations: ->- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/#save-and-open-a-pdf-document-in-mobile) ->- [Web platform](https://help.syncfusion.com/#save-and-download-a-pdf-document-in-web) +>- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) +>- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) >- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/#save-a-pdf-document-in-desktop) ## Export DataGrid to PDF document diff --git a/Flutter/datagrid/overview.md b/Flutter/datagrid/overview.md index 387528f0f..c1651dc37 100644 --- a/Flutter/datagrid/overview.md +++ b/Flutter/datagrid/overview.md @@ -13,7 +13,6 @@ The Syncfusion® Flutter DataGrid is used to display and manipulate data in a ta ![Overview Flutter Datagrid](images/overview/flutter-datagrid-overview.png) - ## Key Features ### Data Presentation diff --git a/Flutter/datagrid/right-to-left.md b/Flutter/datagrid/right-to-left.md index a9d2bd8bf..b8191ca63 100644 --- a/Flutter/datagrid/right-to-left.md +++ b/Flutter/datagrid/right-to-left.md @@ -76,7 +76,7 @@ import 'package:syncfusion_flutter_datagrid/datagrid.dart'; ### Changing the locale to RTL languages -Change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) property of [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html) to an RTL language such as Arabic (`ar`), Persian (`fa`), Hebrew (`he`), Pashto (`ps`), or Urdu (`ur`) to enable RTL rendering. +Change the [locale](https://api.flutter.dev/flutter/material/MaterialApp/locale.html) property of [MaterialApp](https://api.flutter.dev/flutter/material/MaterialApp-class.html) to an RTL language such as Arabic, Persian, Hebrew, Pashto, or Urdu to enable RTL rendering. > **Note:** The `flutter_localizations` package is required. Add it to your `pubspec.yaml` file: > From 2b01e21b602c89aaaaa56b1bef1a7f934488546c Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 18:01:33 +0530 Subject: [PATCH 16/18] FLUT-1038842-[others][flutter]: Modified Links --- Flutter/datagrid/export-to-pdf.md | 7 +------ Flutter/datagrid/placeholder.md | 2 -- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index 960b5f613..4862d330d 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -134,12 +134,7 @@ The following code illustrates how to create and display a `SfDataGrid` using th ## Save the PDF document as a file -To save the file as a PDF document, platform-specific code is required based on the target platform: - -> **Note:** See the following documentation for platform-specific file saving implementations: ->- [Mobile platforms (Android/iOS)](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile) ->- [Web platform](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) ->- [Desktop platforms (macOS/Windows/Linux)](https://help.syncfusion.com/#save-a-pdf-document-in-desktop) +To save the file as a PDF document, it’s necessary to include [mobile](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile), [web](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) and desktop platform-specific file generating code. ## Export DataGrid to PDF document diff --git a/Flutter/datagrid/placeholder.md b/Flutter/datagrid/placeholder.md index c71ff15ad..c5c600cc6 100644 --- a/Flutter/datagrid/placeholder.md +++ b/Flutter/datagrid/placeholder.md @@ -83,5 +83,3 @@ The following example shows how to add a `placeholder` in SfDataGrid: {% endtabs %} Flutter DataGrid displays a placeholder when there are no rows - -> **Sample application:** — Refer to the [DataGrid placeholder sample](https://support.syncfusion.com/kb/article/19825/how-to-show-an-empty-message-in-flutter-datatable) in the Syncfusion Flutter Examples repository for a complete working implementation. From e0bec6da218457b8829da2c44babe63b64a9e692 Mon Sep 17 00:00:00 2001 From: Gowtham-SF4769 Date: Wed, 8 Jul 2026 18:15:26 +0530 Subject: [PATCH 17/18] FLUT-1038842-[others][flutter]: Removed the failed section --- Flutter/datagrid/export-to-pdf.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Flutter/datagrid/export-to-pdf.md b/Flutter/datagrid/export-to-pdf.md index 4862d330d..75f1615be 100644 --- a/Flutter/datagrid/export-to-pdf.md +++ b/Flutter/datagrid/export-to-pdf.md @@ -132,10 +132,6 @@ The following code illustrates how to create and display a `SfDataGrid` using th {% endhighlight %} {% endtabs %} -## Save the PDF document as a file - -To save the file as a PDF document, it’s necessary to include [mobile](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-open-a-pdf-document-in-mobile), [web](https://help.syncfusion.com/flutter/pdf/getting-started#save-and-download-a-pdf-document-in-web) and desktop platform-specific file generating code. - ## Export DataGrid to PDF document Export the data to the [PdfDocument](https://pub.dev/documentation/syncfusion_flutter_pdf/latest/pdf/PdfDocument-class.html) by using the `exportToPdfDocument` method from the `key.currentState` of the DataGrid. From 365104d4b378ba1ecbad6f090e3f6baa7fe023fe Mon Sep 17 00:00:00 2001 From: mugunthan Date: Fri, 10 Jul 2026 12:09:43 +0530 Subject: [PATCH 18/18] FLUT-1030655: enhancement signaturepad UG --- Flutter/signaturepad/accessibility.md | 53 ++- Flutter/signaturepad/getting-started.md | 435 ++++++++++-------- .../images/overview/signaturepad_overview.png | Bin 0 -> 21088 bytes Flutter/signaturepad/overview.md | 10 +- 4 files changed, 287 insertions(+), 211 deletions(-) create mode 100644 Flutter/signaturepad/images/overview/signaturepad_overview.png diff --git a/Flutter/signaturepad/accessibility.md b/Flutter/signaturepad/accessibility.md index fe4cafbfd..8e0793f21 100644 --- a/Flutter/signaturepad/accessibility.md +++ b/Flutter/signaturepad/accessibility.md @@ -1,8 +1,8 @@ --- layout: post -title: Accessibility in Flutter SignaturePad widget | Syncfusion +title: Accessibility in Flutter SignaturePad widget | Syncfusion description: Learn here all about the accessibility support in Syncfusion Flutter SignaturePad (SfSignaturePad) widget and how to customize it. -platform: Flutter +platform: flutter control: SfSignaturePad documentation: ug --- @@ -14,28 +14,33 @@ documentation: ug The [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad-class.html) can be accessed by screen readers by wrapping the [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad-class.html) widget with the [`Semantics`](https://api.flutter.dev/flutter/widgets/Semantics-class.html) widget. {% tabs %} -{% highlight Dart %} - -@override -Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Semantics( - label: 'Syncfusion Flutter SignaturePad', - hint: 'Mark your signature in this', - child: Container( - child: SfSignaturePad( - strokeColor: Colors.black, - backgroundColor: Colors.white, - maximumStrokeWidth: 5, - minimumStrokeWidth: 1, +{% highlight dart %} + +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class AccessibilityExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Semantics( + label: 'Syncfusion Flutter SignaturePad', + hint: 'Draw your signature here', + child: Container( + child: SfSignaturePad( + strokeColor: Colors.black, + backgroundColor: Colors.white, + maximumStrokeWidth: 5, + minimumStrokeWidth: 1, + ), + width: 200, + height: 200, ), - width: 200, - height: 200, ), ), - ), - ); + ); + } } {% endhighlight %} @@ -45,9 +50,9 @@ Widget build(BuildContext context) { You can customize the colors of the [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad-class.html) using the following APIs to ensure sufficient contrast: -* [`Background`](https://help.syncfusion.com/flutter/signaturepad/getting-started#initialize-signaturepad) -* [`Stroke`](https://help.syncfusion.com/flutter/signaturepad/getting-started#customize-signature-stroke-color) +* [`Background`](getting-started.md#initialize-signaturepad) +* [`Stroke`](getting-started.md#customize-signature-stroke-color) ## Easier touch targets -The [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad-class.html) has a touch target size of 48 × 48 pixels, which meets accessibility standards. +The [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad-class.html) has a touch target size of 48 × 48 pixels, which meets accessibility standards. \ No newline at end of file diff --git a/Flutter/signaturepad/getting-started.md b/Flutter/signaturepad/getting-started.md index cc34fbfa7..5c118a199 100644 --- a/Flutter/signaturepad/getting-started.md +++ b/Flutter/signaturepad/getting-started.md @@ -9,18 +9,13 @@ documentation: ug # Flutter Signature Pad Getting Started (SfSignaturePad) -This section explains the steps required to add the SignaturePad widget and its elements such as minimum and maximum stroke widths, stroke color, and background color. This section also covers how to save the signature as an image, clear the existing signature in SignaturePad, and handle the [`onDrawStart`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawStart.html) and [`onDrawEnd`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawEnd.html) callbacks in the SignaturePad widget. +This section explains the steps required to add the SignaturePad widget and its elements such as minimum and maximum stroke widths, stroke color, and background color. This section also covers how to save the signature as an image, clear the existing signature in SignaturePad, and handle the [`onDrawStart`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawStart.html), [`onDraw`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDraw.html), and [`onDrawEnd`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawEnd.html) callbacks in the SignaturePad widget. To get started quickly with our Flutter SignaturePad widget, you can watch this video: -To get start quickly with our Flutter SignaturePad widget, you can check on this video. - - - - ## Add Flutter SignaturePad to an application Create a simple project using the instructions given in the [Getting Started with your first Flutter app](https://docs.flutter.dev/get-started/test-drive#choose-your-ide) documentation. @@ -37,7 +32,7 @@ syncfusion_flutter_signaturepad: ^xx.x.xx {% endhighlight %} -N> Here **xx.x.xx** denotes the current version of [`Syncfusion Flutter SignaturePad`](https://pub.dev/packages/syncfusion_flutter_signaturepad) package. +N> Here **xx.x.xx** denotes the current version of [`Syncfusion Flutter SignaturePad`](https://pub.dev/packages/syncfusion_flutter_signaturepad/versions) package. Refer to [pub.dev](https://pub.dev/packages/syncfusion_flutter_signaturepad/versions) for the latest version. **Get packages** @@ -54,7 +49,7 @@ $ flutter pub get Import the following package in your Dart code. {% tabs %} -{% highlight Dart %} +{% highlight dart %} import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; @@ -66,23 +61,28 @@ import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; After importing the package, initialize the SignaturePad widget as a child of any widget. Here, the SignaturePad widget is added as a child of the Container widget to get a position and size. Also, a background color is applied to show the SignaturePad widget with a white background. The default [`backgroundColor`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/backgroundColor.html) is `Colors.transparent`. {% tabs %} -{% highlight Dart %} +{% highlight dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Container( - child: SfSignaturePad( - backgroundColor: Colors.grey[200], +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Container( + child: SfSignaturePad( + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, ), - ), - ); + ); + } } - + {% endhighlight %} {% endtabs %} @@ -93,24 +93,29 @@ Widget build(BuildContext context) { You can customize the stroke color of the SignaturePad widget by using the [`strokeColor`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/strokeColor.html) property. The default stroke color for the dark theme is `Colors.white` and the default color for the light theme is `Colors.black`. {% tabs %} -{% highlight Dart %} +{% highlight dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Container( - child: SfSignaturePad( - strokeColor: Colors.green, - backgroundColor: Colors.grey[200], +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Container( + child: SfSignaturePad( + strokeColor: Colors.green, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, ), - ), - ); + ); + } } - + {% endhighlight %} {% endtabs %} @@ -119,94 +124,123 @@ Widget build(BuildContext context) { The width of the signature stroke can be customized by setting the [`minimumStrokeWidth`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/minimumStrokeWidth.html) and [`maximumStrokeWidth`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/maximumStrokeWidth.html) properties. The [`minimumStrokeWidth`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/minimumStrokeWidth.html) defines the minimum thickness of the stroke and the [`maximumStrokeWidth`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/maximumStrokeWidth.html) defines the maximum thickness of the signature stroke. The stroke will be drawn in [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/SfSignaturePad.html) based on the speed of the stroke gesture within its minimum and maximum stroke width ranges. This makes the signature appear more realistic. {% tabs %} -{% highlight Dart %} +{% highlight dart %} -@override -Widget build(BuildContext context) { - return Scaffold( - body: Center( - child: Container( - child: SfSignaturePad( - minimumStrokeWidth: 3.0, - maximumStrokeWidth: 6.0, - backgroundColor: Colors.grey[200], +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Center( + child: Container( + child: SfSignaturePad( + minimumStrokeWidth: 3.0, + maximumStrokeWidth: 6.0, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, ), - ), - ); + ); + } } - + {% endhighlight %} {% endtabs %} -## Save signatures as images in Mobile and Desktop platforms +## Save signatures as images in mobile and desktop platforms -You can save the signature drawn in the SignaturePad as an image using the [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method as shown in the code example below for Android, iOS, and Desktop platforms. Since this [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. Optionally, the `pixelRatio` parameter may be used to set the pixel ratio of the image. The higher the pixel ratio value, the higher quality image you get. The default value of the pixel ratio parameter is 1. +You can save the signature drawn in the SignaturePad as an image using the [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method as shown in the code example below for Android, iOS, and desktop platforms. Since this [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. Optionally, the `pixelRatio` parameter may be used to set the pixel ratio of the image. The higher the pixel ratio value, the higher quality image you get. The default value of the pixel ratio parameter is 1. {% tabs %} -{% highlight Dart %} - -@override -Widget build(BuildContext context) { - GlobalKey _signaturePadKey = GlobalKey(); - return Scaffold( - body: Column( - children: [ - Container( - child: SfSignaturePad( - key: _signaturePadKey, - backgroundColor: Colors.grey[200], +{% highlight dart %} + +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatefulWidget { + @override + _SignaturePadExampleState createState() => _SignaturePadExampleState(); +} + +class _SignaturePadExampleState extends State { + final GlobalKey _signaturePadKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Container( + child: SfSignaturePad( + key: _signaturePadKey, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, - ), - RaisedButton( - child: Text("Save As Image"), + ElevatedButton( + child: const Text('Save As Image'), onPressed: () async { - ui.Image image = - await _signaturePadKey.currentState!.toImage(); - }), - ], - ), - ); + final image = await _signaturePadKey.currentState!.toImage(); + }, + ), + ], + ), + ); + } } {% endhighlight %} {% endtabs %} -## Save signatures as images in web (Desktop browser) +## Save signatures as images in web (desktop browser) -This is similar to the mobile and desktop platforms. You can save the signature drawn in the SignaturePad as an image using the [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method as shown in the code example below for the web platform (Desktop browser). Since this [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. Optionally, the `pixelRatio` parameter may be used to set the pixel ratio of the image. The higher the pixel ratio value, the higher quality image you get. The default value of the pixel ratio parameter is 1. +This is similar to the mobile and desktop platforms. The same `toImage()` API can be used in a web desktop browser, as shown in the following example. Since this [`toImage()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toImage.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. Optionally, the `pixelRatio` parameter may be used to set the pixel ratio of the image. The higher the pixel ratio value, the higher quality image you get. The default value of the pixel ratio parameter is 1. {% tabs %} -{% highlight Dart %} - -@override -Widget build(BuildContext context) { - GlobalKey _signaturePadKey = GlobalKey(); - return Scaffold( - body: Column( - children: [ - Container( - child: SfSignaturePad( - key: _signaturePadKey, - backgroundColor: Colors.grey[200], +{% highlight dart %} + +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatefulWidget { + @override + _SignaturePadExampleState createState() => _SignaturePadExampleState(); +} + +class _SignaturePadExampleState extends State { + final GlobalKey _signaturePadKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Container( + child: SfSignaturePad( + key: _signaturePadKey, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, - ), - RaisedButton( - child: Text("Save As Image"), + ElevatedButton( + child: const Text('Save As Image'), onPressed: () async { - ui.Image image = - await _signaturePadKey.currentState!.toImage(); - }), - ], - ), - ); + final image = await _signaturePadKey.currentState!.toImage(); + }, + ), + ], + ), + ); + } } {% endhighlight %} @@ -217,47 +251,55 @@ Widget build(BuildContext context) { You can save the signature drawn in the SignaturePad as an image using the [`renderToContext2D`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/renderToContext2D.html) method as shown in the code snippet below. Since this [`renderToContext2D()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/renderToContext2D.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. {% tabs %} -{% highlight Dart %} - -@override -Widget build(BuildContext context) { - GlobalKey _signaturePadKey = GlobalKey(); - return Scaffold( - body: Column( - children: [ - Container( - child: SfSignaturePad( - key: _signaturePadKey, - backgroundColor: Colors.grey[200], +{% highlight dart %} + +import 'dart:async'; +import 'dart:html' as html; +import 'dart:typed_data'; +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatefulWidget { + @override + _SignaturePadExampleState createState() => _SignaturePadExampleState(); +} + +class _SignaturePadExampleState extends State { + final GlobalKey _signaturePadKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Container( + child: SfSignaturePad( + key: _signaturePadKey, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, ), - height: 200, - width: 300, - ), - RaisedButton( - child: Text("Save As Image"), + ElevatedButton( + child: const Text('Save As Image'), onPressed: () async { - - //Get a html canvas context. - final canvas = html.CanvasElement(width: 500, height: 500); - final context = canvas.context2D; - - //Get the signature in the canvas context. - _signaturePadKey.currentState!.renderToContext2D(context); - - //Get the image from the canvas context - final blob = await canvas.toBlob('image/jpeg', 1.0); - - //Save the image as Uint8List to use it in local device. - final completer = Completer(); - final reader = html.FileReader(); - reader.readAsArrayBuffer(blob); - reader.onLoad.listen((_) => completer.complete(reader.result)); - Uint8List imageData = await completer.future; - - }), - ], - ), - ); + final canvas = html.CanvasElement(width: 500, height: 500); + final context = canvas.context2D; + _signaturePadKey.currentState!.renderToContext2D(context); + + final blob = await canvas.toBlob('image/jpeg', 1.0); + final completer = Completer(); + final reader = html.FileReader(); + reader.readAsArrayBuffer(blob); + reader.onLoad.listen((_) => completer.complete(reader.result)); + final imageData = await completer.future as Uint8List; + }, + ), + ], + ), + ); + } } {% endhighlight %} @@ -270,33 +312,43 @@ N> Since Flutter uses two separate default web renderers, here we have two diffe You can clear the signature drawn in the SignaturePad using the [`clear()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/clear.html) method as shown in the code snippet below. Since this [`clear()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/clear.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. {% tabs %} -{% highlight Dart %} - -@override -Widget build(BuildContext context) { - GlobalKey _signaturePadKey = GlobalKey(); - return Scaffold( - body: Column( - children: [ - Container( - child: SfSignaturePad( - key: _signaturePadKey, - backgroundColor: Colors.grey[200], - ), - height: 200, - width: 300, - ), - RaisedButton( - child: Text("Save As Image"), - onPressed: () async { - ui.Image image = - _signaturePadKey.currentState!.clear(); - }), - ], - ), - ); +{% highlight dart %} + +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatefulWidget { + @override + _SignaturePadExampleState createState() => _SignaturePadExampleState(); } +class _SignaturePadExampleState extends State { + final GlobalKey _signaturePadKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Column( + children: [ + Container( + child: SfSignaturePad( + key: _signaturePadKey, + backgroundColor: Colors.grey[200], + ), + height: 200, + width: 300, + ), + ElevatedButton( + child: const Text('Clear Signature'), + onPressed: () { + _signaturePadKey.currentState!.clear(); + }, + ), + ], + ), + ); + } +} {% endhighlight %} {% endtabs %} @@ -306,13 +358,23 @@ Widget build(BuildContext context) { You can get the path collection of the signature drawn in the SignaturePad using the [`toPathList()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toPathList.html) method. Since this [`toPathList()`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePadState/toPathList.html) method is defined in the state object of SignaturePad, you have to use a global key assigned to the SignaturePad instance to call this method. {% tabs %} -{% highlight Dart %} +{% highlight dart %} -GlobalKey _signatureGlobalKey = GlobalKey(); +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; + +class SignaturePadExample extends StatefulWidget { + @override + _SignaturePadExampleState createState() => _SignaturePadExampleState(); +} -@override -Widget build(BuildContext context) { - return Scaffold( +class _SignaturePadExampleState extends State { + final GlobalKey _signatureGlobalKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Scaffold( body: Column( children: [ Container( @@ -324,15 +386,15 @@ Widget build(BuildContext context) { width: 300, ), ElevatedButton( - child: Text("Path collection"), - onPressed: () { - List paths = - _signatureGlobalKey.currentState!.toPathList(); - }, + child: const Text('Path collection'), + onPressed: () { + final paths = _signatureGlobalKey.currentState!.toPathList(); + }, ), ], ), - ); + ); + } } {% endhighlight %} @@ -343,29 +405,34 @@ Widget build(BuildContext context) { The widget allows you to handle the [`onDrawStart`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawStart.html), [`onDraw`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDraw.html), and [`onDrawEnd`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawEnd.html) callbacks for every stroke updated to the SignaturePad. The [`onDrawStart`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawStart.html) callback will be called when the user starts signing on `SfSignaturePad`, the [`onDraw`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDraw.html) callback will be called when updating a stroke on the [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/SfSignaturePad.html), and the [`onDrawEnd`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/onDrawEnd.html) callback will be called when the user completes signing on [`SfSignaturePad`](https://pub.dev/documentation/syncfusion_flutter_signaturepad/latest/signaturepad/SfSignaturePad/SfSignaturePad.html). {% tabs %} -{% highlight Dart %} +{% highlight dart %} + +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_signaturepad/signaturepad.dart'; -@override -Widget build(BuildContext context) { - return Scaffold( - body: Container( +class SignaturePadExample extends StatelessWidget { + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( child: SfSignaturePad( backgroundColor: Colors.grey[200], onDrawStart: () { return false; }, onDraw: (offset, time) { - Offset offsetValue = offset; - DateTime dateTime = time; + final offsetValue = offset; + final dateTime = time; }, onDrawEnd: () { - print("Signature has been completed in Signature Pad"); + print('Signature has been completed in Signature Pad'); }, ), height: 200, width: 300, ), - ); + ); + } } {% endhighlight %} diff --git a/Flutter/signaturepad/images/overview/signaturepad_overview.png b/Flutter/signaturepad/images/overview/signaturepad_overview.png new file mode 100644 index 0000000000000000000000000000000000000000..afa6afc201f99a1f5bcc13a060688351fca9d17e GIT binary patch literal 21088 zcmeIacU;ZwA3uKL&WPkjMl?{UsA$o?g*u|NX^KRpp}mxu+e%JTrKHk6(U8+bXiLkH zmZ;NG(H^Sb^Xl^*zdwHe|JKLj_7L}ZkLz{4#`F1ny{>cngr*uN2M-5@LgA#UAJU;v z7ROU4i};o;!M~(Edh3Nh*qn9L4pQhJxAfvKf1Us5_&*fNiw7(ISg_;o%N^BEIa4TW zT*z;>HYEZ0oLOHe3fmV>P23qS2!e03f9;q>xF!sO4_YyQHjD3mKg z%dj&1(pas|M*a*H2wX(|-2IOLSqSCiH5Fn8%JaYedxQVl;Qv{EAggw*-a7iw2dDj8 z@?559-@l)69hjCr!1xRPs*>mI?5xW-q%b^EnYxILy>sxRmx+O@K=mOil`7}Sy74he ze*3Kw3$excaGAj1;GoFgCI=HVf*&R(CNfsuU9B!zp3tKq=P`PPZd$xUR#ui<%;e0oOXia6)VC+r3+K1edwMP$K60d@*G1%kJD!&gKR1E7P;i*Bqs#7&5eOUgLPw99X_Ae$#F- zCCz5H`K`A~VvmN1BpbG0>Z zqpSA0ieT+>no#w*g^!n&l&J31jQVtY?M^+3q$h)^IwdXFj=i&ew(nDyXqfBXzNf>i z>Qtw$ibs{?^Se*bO%8NbM;dO36YCoesbuZj_xDw)#isZ21QHZvNgfdBSD)RaICkFc z(_1Baxr`<<>Ynly0n`J29)7I z*W*$9wRN8z(>`?Q21AgVqMsW2A%Hg(Pk*H0CoCglV9TU8ZZP+WZA>-HXN`2%Way_F z^j=-cCo#I1vXB3&lx;_-DMf|8hL<<}@9jq};4N}*)aJSN+q}NQHvKcJhP+~n{>G5_ z0?&~Y)my8KihLNMVx}o|2^t#0xx=eAO1y4ag&U}$_IL7}uZh;rcN-XO^B&s7it+fq zJpEMG5eo|oVgj$xo~``+{HisrHucZ$`%ZOj$gyiSpk<#eT~!^e*xa%NcR51t!eN+U zrhk12XSQp<0n?;3fS3F4zhk>9!}@F0>gV0kzrVlRKT@M?sILC6p!LV710>BkNduz@ z81}U0=k~8}#jEzkJy5Fq*_5UKM1{@SHm@R5Hsiy+P1_@@pDE8xs{a1{d*P}*2w^@iX3Pq}FQ6cM8SM(llKyo(yA!GM-<6CPhImd5T1e3kS`dDl5C?4{tA1m=FY@7Ri zd6%9i2^wKmlPm7cRm7^^5+tZBmq0J4;5XNo+SbKW>A#87-dwQ(?_+Eukggr)kHYpp zth$kSLPN5y>5mWhH}^+66zv^7X)!-HyQT)Wa9lwwQMyslE4%-dO=C)g(q*q_b_2tP zaN+nbUruuGG1BX*2$2k9qm(tm@2+g=c%VG@3GpFBEh;K9D)4wAVvu&hzS5<5elA}y z`BawG!W#I<8n(yVr*EUW_BE8RvCyNr4Ylo|rUl@cn}H`)0vsoQSukHT=JvK-gf-WQ z0$a8$Sb6(8VV!rbJ|i~Cjc$W2!qgP=;-ZD+EV$Y-&*9EXyru8oZ?Z9uQdrO{8S_k&u(XVi-6=WyXQYM}zYx;@^G;{8Z5of>8gWv@goEV^!Hs5paenxFRpdC@T8Xo!^U=iRF2Uh-}~!x7+d z&yGh%z=*GJfLD|~{PX9}=u~%%?U&~k{!_T$DP$$-s)R&jI1L&yzctyig;!AXo*Bp; zE8iKDbfNYsodHCXa_PqhIlsArSXss0M%n5|o34SL{ZU+a-+m;IP;qm5VBl(I3p`uD z(93m?S;3c2k?RvRAJ^eu8uMIj*_SRwN%$Y{!i`W#KxRrkTN*%Tgokf*?f-ndHQ${% z*qYBdJ8`DBE@4e>KU}?(*v};HVpC>>qW8-k$0Opm9lrC5wL#1z3Ar`}2~W;*IKCq) z|AoizGuXhR;zg5BiC5TPCu`RC@$nh05Y4#I{qZr+KFfb&;W-NWX(zSqnqM~7#;I}U z_&I%lw;X@Fzwo#X3y(`a{pK2vv`z5bpAoJ58}}Y$V`HO#jgYoow`R@L&^^XB17CCe zN9HOTUj3{#yq!I^|CbkMd1URQI5vp=Od)33+ksw8=<}-y8$CNE6n5wsBnI@xF6+ z1cjxf8l;y}D07=|#g*n?zkk;TZdG;p_L^4aM2I)yjxt#5&$(GIUj6SJ>-rDUxhOx1$W%5> znL=-{EI*RUzVTgbd8O?={;tE9GNXd8Sq@wdsg*J4S0;rrzckhh4=2Q zZCOMq^AFf^;3;-A1#XYPd&JmH&2#Ly*5>hp^YU1uA&Umfr;iUbr#g3kBtF7eX?Xyl zq=Uq@(isW6zS*JJE_`w3VgPwYe*4L=6)RQ*wb~ojFL@Br97sL6mDrO29Ga9>)kf#? z1Olcc&j%0&r1@A*SVH2He)Eg7w~pM~7%QTm@@jk^duApg=dD7*;-#y?6Di;5eB1}vmcF@3(yGipx4+TQTsmy7b}^U2la7*G zwr~ieV&6g}$DtHEY~OaZ06i>uv~2r>o_Z~1>8KT!FYz{}ghThd zDf*%%3X~R7iz)8p#;DTT45zNqcWbr6E8P>c9N7PXnsdtlrg=>armx>)v~fB!58$Z}UfDR-&+Hl;6uVWj zmHHKAo42r~ytGt}OK~)?pr8O@$JP6OgSp;`6M+m)zq3f5M)_{(O4B{tOa7E_Derc7 zcPBKW(0hXAsolBjum6qLoeRdl+D0IW75y33aP6&o54)`0soC%;R<*j`uae0$B;^A* zp*mrA7mU>aJGl;bQtjG{T1_;AUfMO=AZ4C~fl6rZhT2^8E zoh|oOB66TatVU{d@=r?Ig@To8-U;@a6g03I79retz)b5)=!OekFg>h@>mGUOO-=x$p{`ok8J;Z*z9njEO6`a z$cW@98-q93*@^pNikLpg$QT(@g&A;E}obMcH4Q+SgV%vq$tj zc#8ied-smF?9%ovU$~F(`~A6O*P5pvr}kjSy+vhfNZ$H$-@5*p@c#WLAIrJ!3#&T} zwhG9bxMG8tI*rsrK1Hwa<~iDf2M?C4+LFY%S!N?E238?#P3-}nbd_-zOTVf?pHwd% zufdzG_OkafOc-Z2c3Xk1>iz!yJ_p2&Fa}YBv`_Bsm)$k~T}lxpnRs%={Opil4iG50 z+2K3u_J-B(-nUOD-6+S&u3raPmgGxm+s{(Db8)~R?Q4F)zv6(%ICqkX5XsXAC#wqwV^m-cLdLceqOQz(8G6~V$N zUp)IApD=>0Uc7kG*OZlrXxc#qZwW{6$HQ$RjEBB}q;cjBK8x6Y=_zEib4{VU9zJ|X z|Dls`G+8S~$=}P!!`plF2ZrJkG2lnMsY@%L;_26vbmLr2E~UvQ3~oy1jh5M589cKC z+>S7#2w4aE9d6NxO6&2@#tzm%$uz>IZQfjCPccZ3U<}Y3QVq4R(UMxA)R}G&F_3N> zfO@OCR=SR8%tG?28*6(1SPFmG?S(dwb=^hllqy)KzRzL4LN`*zFP~ZvOcS+hRR1A0(cGq;L`C1pD2XVcrfQ z;MA%G5La@GtDlq+Y{V!Mc4VdX8ptF_xoy&XfP(x)o$Y?tGn~&4 zH0NrerpV+jRtY@}(Dd5!?TzI+6?Qqj14t@*aBsn62orsE33nMn)da@Dc{a14Q79rg z+EzzMPY+j$>%VfefFj#R>O+4Jpw-7IddX+( z%U3IUjXLs{zI)dLCzfmwN_OmcOX?Zeydaf;Cu9@nN{-G#uwF-A`Nx{717_*w#b(;t z+Vo4v)%pbAMhO)HM2V8OapMK@GDLr(&_2c}XMo)#sa##; zpZo1u7<50qqn>V~Ed9!RpRvc%7r%Uxj)sB;_`|74>-_N}4kok(M&jV$&;h9Vnr$8T zaJw4P*Vk%MPqlz8dm9EDQFkpjGSiKj5+CVSAET1tuQt$#Xz_$H1ESX7SiV*dK2Mxu zfsP0se=OHHRxGRR{)kV^yeJKcU!4ZDoN$ZZ_e%>c)_)ampInhs*B#r)z-DVW+xX9> zID>Q}s&Gx+XH@2~pZ$eNpm+WIw{CrtqqCa|@yqbmDqg(|Geu8tZ&B1_qIKlC^gb0c z&D$jBQE7)_kV)M9lmjHSngrqvtmK{rBHqy$NBE zXhej&W~98wFG|}ql(ldOJofPLC~KYlkY{r8WcW|F{0N!JcH{Dg3_^4|y@-kncx~p{ z72?7bMcU>Su4$`Its*G{H=LwQBtOsCcHubM~p> zzO&QG*n3v*Zae%NQY~Z2%8de4Qr=tvO$&d2*z7km&rNaKX5Un;(vrD?a;lx&Xl`c6 z7Ln-n`~8OME~$R--O$~qwj~r4eoo=mp%OJULdyCnI&H$|v_2uidhiC)xoz9FZv98n zs_N5HexGk&<*bmP`#z^fGW2Ou$V#A_wZ96IPNCp6WSAGre?8OPSsp}?qKth@PeiJ2 zVu0_=fUK&y!Fs6Dkj#7TiWddy*w+wcf)8lRS@g=vcYE>|5Z@IOQ86)15(h8Nyl*J< zc84{=y9PMopoYGXLZ<-KND5qzNtDCcnF%Ih-?As47dm<2bYJS%mv)iJWr9?%xv6dk zPd8_*mJn%3#ACS@F314Wu))wS+z3(=vBzdsG*tJJ{i5DOg%c2ZzH`LQPu2Kk18TnA zb;aZXQIm2Y04D;fT|lMZ-|=$A}PqU79udX$RZ$201o8RN?Hnks!gNlZv23{CV4OGDG(B2 z+&p{F-1z?E$Jm#%53GrXC24gJl2+9KC9t0;fDDqw2<(TQQvtJBP7$OOqYQ@%-n?<+ zWRaX#R&KkmG3toR{Qq?;DVgun{_Jql2Am6GKS~x zCeTE`8PZGageFwKGKG+H1VEu-LzI+N{7PwO-rwoP!#;B<|2ggPW-X=Djp(9u!jyU{ zLPWg=a+sD`O;ue|Gr%Vx6g#PX^@$IzUAtDbCo}?us$;5#lzN1Xe{^vc%4M-hY#NF_ zfmBGNNvKZrsqDY%!1Q`RTl^Vmd2e4q=~Emo+fJ}YLU7pnf%al^0?2b0{f}nKQAF(t zkiEuO)uqnD)kyxP7VkhpL6M|$EtexwbdjG-e%d88{$DgtfY#h*TX zDg_`-#LrZNbefKtQ8udn_&WCgC}Ev)@U&n-#gQsWmQKWD1<$&%eQ^*`lTa{Np}UDT z;x$@3Z|5%IgvJW&3J4iQx`dxTolu+|txq}m;;BCuzx{qg8j{NsEFc-Im=+IFIKtTE z;K73{e*koE{9r|lFw|B!HjvxiHh#a5G=7qgaHg)W?BRBLqv1kD z;~Y!td#J|8NF7o`iIsNk(}R*;Bh7?UFgbbvEFJn}@;s%-Gp_X`JR6bpo0a0cvXIpx z6Zf@%(c+)95NF4{Ck8{Rt?I!Kvhm~YnKTKC<++7Gy43S&De@gHLwD_t zV<(DyrjUEC$S-t@c%VcE>AbX{Isl#RO$)FpJ-@8KAvq3#(KkKTPdAU0u_HR2>+G~E z6f+}aM9COd-G9teEv}JwiXgt17f&(wyJmdW^BWs)C234AS;wD&)VJxwrmh<0`G(nv z_6&eD5flV;445<_4dMfEsy5K3R|KA`&;zGUI#sz8<3B!@2W67+8oj^_6-G(O-s*Dh zJR~W@+NXyh6D1QU1JN5&`4|MnN0qdAXzlp{vPd`3obo=PK7X+@3`PHnq@RtfMT-}6 z{up%wI(Gf}h4AYJd_F|k&zF-=;Uqde&B{vc9F$j*|9OeLGY4FHP9WtF+z%@prEzeJ zbQ;~Rz8@iD*OzDKiCV+T6x=kv>o_{6gexWSEBSnJopDG(j9x$nplkXd{+bUUYe8C0jPO5eR&XtS z=%`+YVfHI6{-ng$et5tyK3mcjK9ORaYoF&ema;%A7m(5(MqTw*F)^`^Cp5acyA#oO zOF_z@Gcd%^hu%)G&b96V;M#uxiKVsLgHS|81qBajgzkQ*V_=57mjW!PSXvOwLCKT@ ze-S9<;NoJoFr4*)^MMLJLZ$?XByAF%3d#E{;}gzVkrTV_2L#A8*nbA?G&V?YM~48p zu^-{(Kc$Dp2rD`NCHfzPI`W_g4XBV1+z4Rpo@o4qozk*t;W^VaeskMfS)T8+Gn)sz z(4R8-0Xz1+S;{Xp+G!)Jr`7&2MAVS55W1ZS(sz7D(ezQ+Q5$j> zNk7L39q!x@Jfz!Rbh!&)oCqQ&nptQ_eQ|Bcu{9*Z`H7l=iZJmZxwbsl)L1up1Qsd6 z=fg?k!(t0Ga3qV(tig9st{c#wB()Ca(Wx-Y_Cq8oURI>2OcOQ2DGL5)4u%TFFr3fh z8=LciXs~cXziOl4B+wB8=$1p1_ox+SMha7hTzz~Bjs$E; zCQ<+-Z(2Ou#u`8H9B_&!XbuCUyB9L*E>h<~b4hOtS*r$10(xt9H34-aI`fHJE zaAAXJUj5xbQ}vg*%AY@%m_@Ter=ssdpGMGWDYu^|nZM2L+MVR*=H~9)yC`On6KnJS)HEvE(`Mj`*jYQ%l0tzIJLWuUjq^$*V zMkwxz(>-zia`6*w-bl@(LAEVP+S^rUhwg1TQ0FS2t+S{P`hf03Dqll{z$Zq71F;LU~1chJQp+g3Cbjl%FsYveDP+3Efa`foJO#Z`IhQ1?lv zhv@<0Zd3d8W^8xHJzjYOpb&{F#hIU3xj%Jn)?;!9t*YKf=c6xG=h(Lzp&I?*VN;P= zSj94j;@Owz4>lD0`4Jq9tw8o*1l)zryEDe84&G%yr=mhb273miq*`N6oE*Ds9d3&U zVrJ%SczzRdz!>%=Mg8G67~rNLnJ%1$u9pMfcJX_}O%XUtV0=>>Rv>lu!%6~`P*u@z zcn=GjmZGKq-Sb@}X(<3GeJ0Z@RFsK&7-{GNR~_WD!O+Xy;bfI4OGrHsmqNh`U~^^k-bTLcv_phv#9|DFDwR$ZiDBf_n@0f|oYJWY5sqYms@qh>|Ho zQjc*Y)E8((85oDz7`^?N7CK|3VQ;%-&6+bw-3G)B3JMDsdKfGcB9JOKVfVkkyPcbM zZ^@D+q#;5CO$%R`#p~PErBYDFz_itc-?#!#5GD^Gbhc+H#gd=+_RBHAg?{`tL^MhP zk~tq}ZSl#c#~UxwwRa{e7uaF0f|@)K^8(;;mnRzyiN+=zs(U#6EeQ~c!Gdt|40?VN z#z?1&=Vz3ee?&71oPFS^^NT5&@??9Pn?MdpLk=(61qxJm-E(XV$OCF~7FgQY zP`f!;ivbEgnGsV}L;)aNoq!eyaqYvij8jOBW?sEQg_Ga!`b+eqtp0O-NiU!QP+$US zHTEGp8A5d&ABOox(o615u3A(>VH{Wl6LFXEsLn>GmoRr zfQ%sFJRl?uGFmF?`SfVL7G~lsdc1$VS(*c&10hY5>=9y$(=`k8k^gMnx|M9h%8|o& z*Q2o=C*}LcLr75YLRI))n=j8}edngm8)`v&duiXA0$FwQM^vKS3pgr%+HzzWA(gaFfPez{isiili9F!J3bZ^-}bNIiYQm`7$UAV-31mkBseY0jE%f zTld7eH6&@H`$*c~$w(-0CmDLUa);g zBxlQw-lXx;^d8#1G^PQFI@s3MMqq#o@Rf5U0zZ|EXTZpEPM!bmI2P_$TGRXC{dn4hZCoQjD2#9%3)-hpDNIF>kcqNqq&A>$gk{%*KoQAO zwOtvg=st+1l>4Abi4RCcHqt#Qd4QZDM}v380%+v*2^|goB-`#2C!`UYgzW0?40s$F zxqa(~LJ^4|yJa({WFn6v;sXVRcI=2S#+<+fG-3K$7+L6JC4o`y0SV?Dn?Hd7%ohRf* z$Q%!uZbjZas;+(_M(J`ksBnoV{@zHO6+#t87A)8OUr%sg$oyZx(cbMKJ@81v(wjcw+WnI!H*>sAW9D$`($1Cmo_mclaI)aXtq3AwrQ%6%)eT-Igx?sH|R>2n5oYxfd>DlKD-hs z8)TPAD>m59tcr-7fTQ^zNF2dcITd>?&~KLW8ckZWb}c&fLV%K57#ESvZGAy>2Lu*! zXeja$Tyd+jM#N9RO;X(u+MFXb3M2Q5Ccm$+Yb!Xl{m8vfm_*gZZMTc&Gtl0L`z-|>M;cG z06xW(8#n%%nwl!d*Z@Y!Bx0Nl@$UrN>8Bg%V`jpuC-#;e2r!v?YKgEfnwz#&oc}Z8 z&ww_tFhiST(>O{D2(%^LfccCx(piHF_S}MxvTrS>gSQ4+2_Qwrn*tq;A&=Q0`!4iN zqO8e)Qz@T!mGm6$FgI@ZeCet!pU|uy8)KUHgQK&Cc~fDaKeMy0p#G_t-68ZJ9nTaz zJe}i&}uV0)3e5AYQtK16 z$-Wl*64 z@kPeC=$9NFpTm7fV}GEnu=$fQG}hx0Qo{A-D(sZ`8<^vG&V}lvL1u6;^V68?(7yZc zBSO6pYiglM4_&C-gmn^40aF8jm4+BjLNZRixcLb57rSL~Xgiz$iX|07b>kkL_)@FZu3S%)Db@-20e;dTuI)Qtkn2d#XP7raVabWqv zbl7CaEtd6ll337~Wm!|ooQOqpe*$pbgRnc+Q>*HhZ@MtFV8w>%$k}EIg1m_whEBz6 z#jPMTnfJ(mA!fXZdT-`CbzF_S%by%z8KKGB2S2x<#M96U1MKC zP|Skt=+Dmj_?S#7Mkd0?GB7xH5Y)C1VhK44Gq@4L=V=CHE}}@&;!)|d&YxS4ip$^A zK0lZ1X+)C($;8M|E=@TgImNyFAwpR;_5rzV*f`x4fLS(B=B)sN*3 zL7F7B7E>Ix$T)@uLQ4Zwe&Kat$u}lPc6g)HB#j2pNVXthSY(BsJd`WmWIp~Rt9X7k zqrdAg@JG>t23>ZD9AUt;L3KTe_-ypFq^;}TnJl6RkilJw#v!;UtVoMTQ9nckhFpOa z7aEct5|{|lkqpC59+{LQ{5IWKmQZ*T4DB+O z;e7+GNlJr{Y2ri?Im1zfjSH+KSnAPtcn00rRTiK5mvoV z57eC-Tm<9^Cgs}au$v_Q&F1c4C|5V)eK#zuL)hrGc`kk42^7!6v{be||0;lm&$ z#pwWnp{grEdC1J&mltsuDOxyZMwZg+fEE=Q;uK8wo1Y`c5U!ASj?cw#0O@Md;(>6X znHwz}__~dPtL}h!cH*6%X`c_RwvueXK(r2_o4q?=ba-@_AiA5$04@txY#~_; z{#Q78mbC$JA@er|&Kl6eR^_EozPT-2B8tx9+~f}~5(t1Gve*QQ{ay0b8=y>*LGgw2 zU4CRC`1Ritl>fEC|LuMdaTTX02_ub0>Y)U(3+~)m+4@-BQmANVQyH_=5R(UaZUYfy zVjt=hdY`&Tfj*ags)a1K0kd#a@$aJMdHh}&>Bk3>mE#iUs#e)zPV>Z@CkJWqfOsSc zLqH3jmh|eY`T2YaswjKs3jFVDckbVB#2`M&Z4}D-{Wuf>UagO_nTv+m!z;@U{m;W~ zYd7#G+U3s&mUNsz79$;7=M}i($}uO*Ebz*?sN=+Hig8@@AD`K(J!OafsypVmweQ+E z-2OI>hi zmcd|Gx|WRWcSCi4#)6HTt(UUZ+?FM(Z9k@^sYIF$un!Ql5KzKtk}P0m1&+2_0pvm zd2X{2Q7CB0yRCSzFb>U5O?ByCy|T#3z56l!6ekiDew|*fw2l1v|H?Dyj?RMnAG4^? zWWKw|!P$1-su#w8UEhnpwzjsCabztnE@$CpN4dv1zI;^Et*pZ(yz)R;WMqr3uO~)J zs;jG8a6rofX*Te<&<-JCVPS21`#~q?ZvQaj16?lryBy^#E6)abuji6QUo#JfiCbD2 z(aBM(ZbfO{Qcx`H?1JSNQ=G_YC`-xlerBgj+sWnc9y<#PmDgA5nnjzjXbC@=8Rfl> z6^ffPdaRaUKw4I|ob|XAdt-SP^|EXSjTVHXm4_Uu+tr*hp^9~O*bhwn_B!*F##`=` zJ6ZFvbw4ertE)>`i_72`o4`(-u27L#9Tq5{Wq<0JEF4Djma39WBqLb(`+%G0uQvxH z1cijkYf4KMI4NaTWNkNzi)EOe)t9<1xKpTtS;|y+Y!RiIh>@C>DaWm*xc|Azpj%=5 zP(eQ|R;L6W#sxwqS!<6-2Hr{xLwBLNe$(5rjztzyt*^X2c6CIUYAP8oy>gLMp;LjN z3)fo3xT1q99r?`6?r5n?XeEj!)+bNi_)E#8jKaqkef0U-qih2Cgo>8 z{;lr&CxW!s{B-m5I+vb1!xH3+j(+sAj+3HpuAqwh9=rCq*(LoOcA;Z%M~2I)0Jj-w zhUc#-2P;RxoyOx&MJTTeJIvK7We0J}dCMxLo!QqS^CRgycRcG)k6Cp~byY$;v!va5 ze-t(!kXdCtz~GhLf=XNei8gCVvE|kh7l%U$+&a53+>z)naD;twN7~o_kHMiKex|{-K?!GFWRG3 z;WE>{K4{@b@hZ`GPJ`99}6{CUEu zyhZQbBdAC^>W4Kt4e?{TSst?`I?mI}GokmuyZ+nEJ)Cj;#rgkKvIZLP481t}ON~j! zCbaA^<`35AEo2;=xpr-JJ&p(e%dJCs9$w$u5Rz(mZshmguzl4-ky;n#s@jF9ym?HW z*(2vHvszD@=B=?~_Bl)>X=HdYtZwSjXlvJY_4nIG&#A%d_Zrg6y7@jH=kk6T)A+O8 zxHG2x*_?xne#g@}`qvCwu2kyC9sjwgis-;6K67(U&RK)k0VNkN5TpXy|o0I^k&Mb^FepFu{=Yldo4F z5$cM-$24#Kh^F&X1e`q!W)->uq^I>B$H#MAn_<478;&8|coAl zR8-o#_(PsXE{YjuFKxU1v_zG}w7Cy*%yvx-9?dqj4IQe#&Uj7dt3rc=1yS-U9d2Ss zLUAs13FU6<$@eepg}T4I*(_eT_f~-Xx!j$7S=7j!j$7ALnxACLxnv|9eB+sOu}yQ& z{PeuZ<*c0!+CD#BU3<(lv=mHDUl?XsHx)ddzC5zLgc%giA2!4sv^!s2|ES`je`AhR zRD{(;qcELApQG32o@r2NK0iJ;DhJ?l!seL!MP7Gd2CVSh{b$VUbERulamcwob$GnEF8Ad zm9{q1MiA;h@EsGPdb_vqDEv5+(O*4b+#4q@pQ_g+;C#S&|InUKEtLm)2SQ{cQ&cC6 zXz_@qhWK1&ZzA^$=bL@;UeEn6f2we-*17%@ORLy$LHDM}O+jkngIV!UgYB-G7>Kdh z)GJ2!vvS@)I55pd*|!1ZdpC>4vg(zLPd@W>O_i>@rSTUkwGMY>jPK%wx7ap^SB5z# z)Nfq{%mMBzofCz+ha~nG*6LwvXr^7V9&_TA=Bjt@j9C(E`w z2+jYI;XUB^kN3;=lMl@#X1J=O3l1+GkJ7zech%;z%)6Xz5h-VK-qszDl^k##mj~HkkKdu@ zNCzAUm9&st0G})9gi?{nJqfisA#Dz+~t+m-e0~c-cj2xB;Dgj7uv@$il>)XnMJK#enQ2PxrIP@YA)p(h^L(t{o<6>-}D+vU5xc<4GkG#VWA{Ux!DuZ^i`FHg3$9b4g9u_I_?+QJOqs?$I74 zG0iqJv*Gda9l?M!HMT^Wy29h{j8x>edb6x+*U?Z9{0q+WV4JXZau zzqh}CkCr%>DdQrucJT%mr9UYmdcyHL(nV73!gw;93W7^Zb-P42G(1`x<~sVC{k>V? zGqJ+HzB86-A8(l#cFn{Dho@bZFA<`~7WVOsuP+Shk7+t{HbW#MCPqO~a(-e7rG-~k z?I4fY_GJ(v@P$8j?gY@x&HQ}-eR9CxVdDVL+Y&|8APK2(rBeh+XwX8M!PWc=x820F9bW5ZJV=X^Y zH`32P%lA28q$ItrNmmPN-i4(ptuwdfX2D9CeAn#k95WiHdw(!w|UVBBB@o<_y|F4$-NIoCa7US$Z|GD}0y$!tFLR{_>F6O2hh0)A4 zKXIsAHteA$zF+B_mU^I{*}PP{J>a_ufsF@sViZ?$tgP$mxd1IL+&J)~n3`JuSLyuW z?#h@!3z8nu7jcTYv5Xxf>gTsK9d~ld{1|ih6V%FJWk27p zk(!;6)gSzpQUa?I*ygcgde;>Hfr#7)klWeYk$_H*sKlK5)uO4v5^wa^%bP2W5fb#(LHgHunIlUO#Eks>`Jrh~@5;)N4`Y?b-)x~c zk?*9iJWB{}qVB3&CEO-X8Xi-k$*~{6?p>oy9Tgo+lt-kq`##%HR6dZgV*J|u@UoH& q(VQqaMvN0&|NZ*C|Igdt_k0^qPte}Iv?FAx)We#G=m$?<`#%6iwAwrX literal 0 HcmV?d00001 diff --git a/Flutter/signaturepad/overview.md b/Flutter/signaturepad/overview.md index 9dbe23cd4..c62d93861 100644 --- a/Flutter/signaturepad/overview.md +++ b/Flutter/signaturepad/overview.md @@ -2,19 +2,23 @@ layout: post title: About Flutter Signature Pad widget | Syncfusion description: Learn here all about introduction of Syncfusion Flutter Signature Pad (SfSignaturePad) widget, its features, and more. -platform: Flutter +platform: flutter control: SfSignaturePad documentation: ug --- # Flutter Signature Pad (SfSignaturePad) Overview -The SignaturePad is a widget for capturing smooth and realistic signatures. This widget allows you to save signatures as images and sync them across devices and documents that need signatures. You can use your finger, pen, or mouse on a tablet, touchscreen, or other input device to draw your own signature on this SignaturePad widget. +The Signature Pad widget helps you capture smooth, realistic signatures. It lets you save signatures as images and use them across devices and documents that require signatures. You can use your finger, pen, or mouse on a tablet, touchscreen, or other input device to draw your own signature. + +![Flutter Signature Pad](images/overview/signaturepad_overview.png) ## Features * **Signature stroke color customization** - The widget allows you to set the stroke color for the signatures. * **Signature stroke width customization** - The widget allows you to set the minimum and maximum stroke widths for the signatures. * **SignaturePad background color customization** - The widget allows you to set the background color for the SignaturePad. -* **Save as image** - The widget provides an option to save the drawn signature as an image. This converted image can be embedded in documents, PDFs, and anything else that supports using images to denote a signature. +* **Save as image** - The widget provides an option to save the drawn signature as an image. This converted image can be embedded in documents, PDFs, or any other medium that supports image-based signatures. * **More realistic handwritten look and feel** - The unique stroke rendering algorithm draws a signature based on the speed of the drawn gestures along with minimum and maximum stroke thicknesses, which brings a more realistic, handwritten look and feel to the signature. + +For step-by-step installation and setup instructions, see [Getting Started with Flutter Signature Pad](getting-started.md). \ No newline at end of file