Skip to content

Add sortIconBuilder to DataTable, PaginatedDataTable, and DataTableThemeData - #188729

Open
puneetkukreja98 wants to merge 5 commits into
flutter:masterfrom
puneetkukreja98:fix-91801
Open

Add sortIconBuilder to DataTable, PaginatedDataTable, and DataTableThemeData#188729
puneetkukreja98 wants to merge 5 commits into
flutter:masterfrom
puneetkukreja98:fix-91801

Conversation

@puneetkukreja98

@puneetkukreja98 puneetkukreja98 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Description

This PR introduces a sortIconBuilder callback parameter to DataTable, PaginatedDataTable, and DataTableThemeData to allow full customization of the column sorting indicator icon and its visibility/orientation states.

Key Changes

  • DataTableSortIconBuilder Typedef: Added typedef DataTableSortIconBuilder = Widget Function(BuildContext context, bool visible, bool ascending);.
  • DataTable: Added sortIconBuilder property to DataTable. When provided, it overrides the default _SortArrow widget in table header cells.
  • PaginatedDataTable: Added sortIconBuilder property and forwarded it down to the underlying DataTable.
  • DataTableThemeData: Added sortIconBuilder property to allow setting a default custom sort icon builder globally across the app's theme. Theme fallback chain: DataTable.sortIconBuilder -> DataTableThemeData.sortIconBuilder -> default _SortArrow.

Fixes #91801

Usage Example

import 'package:flutter/material.dart';

void main() => runApp(const MaterialApp(home: DataTableSortDemo()));

class DataTableSortDemo extends StatefulWidget {
  const DataTableSortDemo({super.key});

  @override
  State<DataTableSortDemo> createState() => _DataTableSortDemoState();
}

class _DataTableSortDemoState extends State<DataTableSortDemo> {
  // Initially sorted by Column 0 (Name), Ascending
  int? _sortColumnIndex = 0;
  bool _sortAscending = true;

  // Pre-sorted list by Name
  final List<Map<String, dynamic>> _desserts = <Map<String, dynamic>>[
    <String, dynamic>{'name': 'Cupcake', 'calories': 305},
    <String, dynamic>{'name': 'Eclair', 'calories': 262},
    <String, dynamic>{'name': 'Frozen Yogurt', 'calories': 159},
    <String, dynamic>{'name': 'Ice Cream Sandwich', 'calories': 237},
  ];

  void _onSort(int columnIndex, bool ascending) {
    setState(() {
      _sortColumnIndex = columnIndex;
      _sortAscending = ascending;

      _desserts.sort((Map<String, dynamic> a, Map<String, dynamic> b) {
        final Comparable<dynamic> aValue = columnIndex == 0
            ? a['name']
            : a['calories'];
        final Comparable<dynamic> bValue = columnIndex == 0
            ? b['name']
            : b['calories'];
        return ascending
            ? Comparable.compare(aValue, bValue)
            : Comparable.compare(bValue, aValue);
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Initially Sorted DataTable')),
      body: Center(
        child: DataTable(
          sortColumnIndex: _sortColumnIndex,
          sortAscending: _sortAscending,
          sortIconBuilder:
              (BuildContext context, bool visible, bool ascending) {
                return Icon(
                  ascending ? Icons.arrow_upward : Icons.arrow_downward,
                  color: visible ? Colors.blue : Colors.grey,
                );
              },
          columns: <DataColumn>[
            DataColumn(label: const Text('Name'), onSort: _onSort),
            DataColumn(
              label: const Text('Calories'),
              numeric: true,
              onSort: _onSort,
            ),
          ],
          rows: _desserts.map<DataRow>((Map<String, dynamic> item) {
            return DataRow(
              cells: <DataCell>[
                DataCell(Text(item['name'].toString())),
                DataCell(Text(item['calories'].toString())),
              ],
            );
          }).toList(),
        ),
      ),
    );
  }
}

Working screen-shot:

image

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 29, 2026
@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages labels Jun 29, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a sortIconWidget property to DataTable and its internal _SortArrow widget, allowing developers to customize the sorting indicator icon in the table's header cells. It also adds corresponding tests to verify the behavior of the custom icon widget under different configurations. The reviewer suggests updating the documentation of sortIconWidget to clarify that custom widgets will undergo default animations and offsets, and recommends exposing this property in PaginatedDataTable for consistency.

Comment thread packages/flutter/lib/src/material/data_table.dart Outdated

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once we settle on an API here, we should consider not only applying this to DataTable but also DataTableThemeData and PaginatedDataTable. :)

Comment thread packages/flutter/lib/src/material/data_table.dart Outdated
@puneetkukreja98 puneetkukreja98 changed the title Add sortIconWidget to DataTable for custom sorting indicators. Add sortIconBuilder to DataTable, PaginatedDataTable, and DataTableThemeData Aug 4, 2026
@puneetkukreja98

puneetkukreja98 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

Hi @Piinks, I have updated the PR as requested.

Summary of Updates:

  • Added sortIconBuilder property to PaginatedDataTable and forwarded it to the underlying DataTable.
  • Added sortIconBuilder property to DataTableThemeData to support global theme configuration.
  • Added corresponding unit tests in paginated_data_table_test.dart and data_table_theme_test.dart.
  • Updated the PR title and description to reflect the expanded scope.

This PR is ready for your re-review. Thank you!

Comment thread packages/flutter/lib/src/material/data_table_theme.dart Outdated
Comment thread packages/flutter/lib/src/material/data_table.dart
@puneetkukreja98

Copy link
Copy Markdown
Contributor Author

Hi @Piinks, I've pushed the latest updates. Please take a look when you get a chance.

Thanks!

@puneetkukreja98
puneetkukreja98 requested a review from Piinks August 10, 2026 09:09

@Piinks Piinks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@Piinks

Piinks commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This PR is now ready to move over to flutter/packages!

See #188444 for guidance and git commands to help move the PR over. Thank you!

@Piinks Piinks added the Decoupling: Port to flutter/packages This PR is ready to be ported to flutter/packages. We will provide instructions to do so. label Aug 12, 2026
@puneetkukreja98

Copy link
Copy Markdown
Contributor Author

@Piinks I've ported the changes to flutter/packages#12645. Please take a look.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD Decoupling: Port to flutter/packages This PR is ready to be ported to flutter/packages. We will provide instructions to do so. framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Proposal] Add option to customise DataTable sorting icon

2 participants