Unverified Commit 2f611f14 authored by Per Classon's avatar Per Classon Committed by GitHub

Make header optional in PaginatedDataTable (#69610)

parent 96a78c08
......@@ -37,8 +37,7 @@ import 'theme.dart';
class PaginatedDataTable extends StatefulWidget {
/// Creates a widget describing a paginated [DataTable] on a [Card].
///
/// The [header] should give the card's header, typically a [Text] widget. It
/// must not be null.
/// The [header] should give the card's header, typically a [Text] widget.
///
/// The [columns] argument must be a list of as many [DataColumn] objects as
/// the table is to have columns, ignoring the leading checkbox column if any.
......@@ -64,7 +63,7 @@ class PaginatedDataTable extends StatefulWidget {
/// both have defaults, though, so don't have to be specified).
PaginatedDataTable({
Key? key,
required this.header,
this.header,
this.actions,
required this.columns,
this.sortColumnIndex,
......@@ -82,7 +81,7 @@ class PaginatedDataTable extends StatefulWidget {
this.onRowsPerPageChanged,
this.dragStartBehavior = DragStartBehavior.start,
required this.source,
}) : assert(header != null),
}) : assert(actions == null || (actions != null && header != null)),
assert(columns != null),
assert(dragStartBehavior != null),
assert(columns.isNotEmpty),
......@@ -103,17 +102,19 @@ class PaginatedDataTable extends StatefulWidget {
assert(source != null),
super(key: key);
/// The table card's header.
/// The table card's optional header.
///
/// This is typically a [Text] widget, but can also be a [ButtonBar] with
/// [TextButton]s. Suitable defaults are automatically provided for the font,
/// button color, button padding, and so forth.
/// This is typically a [Text] widget, but can also be a [Row] of
/// [TextButton]s. To show icon buttons at the top end side of the table with
/// a header, set the [actions] property.
///
/// If items in the table are selectable, then, when the selection is not
/// empty, the header is replaced by a count of the selected items.
final Widget header;
/// empty, the header is replaced by a count of the selected items. The
/// [actions] are still visible when items are selected.
final Widget? header;
/// Icon buttons to show at the top right of the table.
/// Icon buttons to show at the top end side of the table. The [header] must
/// not be null to show the actions.
///
/// Typically, the exact actions included in this list will vary based on
/// whether any rows are selected or not.
......@@ -337,8 +338,8 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
// HEADER
final List<Widget> headerWidgets = <Widget>[];
double startPadding = 24.0;
if (_selectedRowCount == 0) {
headerWidgets.add(Expanded(child: widget.header));
if (_selectedRowCount == 0 && widget.header != null) {
headerWidgets.add(Expanded(child: widget.header!));
if (widget.header is ButtonBar) {
// We adjust the padding when a button bar is present, because the
// ButtonBar introduces 2 pixels of outside padding, plus 2 pixels
......@@ -347,7 +348,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
// inside of the button to line up with the 24.0 left inset.
startPadding = 12.0;
}
} else {
} else if (widget.header != null) {
headerWidgets.add(Expanded(
child: Text(localizations.selectedRowCountTitle(_selectedRowCount)),
));
......@@ -432,6 +433,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
if (headerWidgets.isNotEmpty)
Semantics(
container: true,
child: DefaultTextStyle(
......
......@@ -229,6 +229,43 @@ void main() {
expect(tester.getTopRight(find.text('8')).dx, tester.getTopRight(find.text('Rows per page:')).dx + 40.0); // per spec
});
testWidgets('PaginatedDataTable with and without header and actions', (WidgetTester tester) async {
await binding.setSurfaceSize(const Size(800, 800));
const String headerText = 'HEADER';
final List<Widget> actions = <Widget>[
IconButton(onPressed: () {}, icon: const Icon(Icons.add)),
];
Widget buildTable({String? header, List<Widget>? actions}) => MaterialApp(
home: PaginatedDataTable(
header: header != null ? Text(header) : null,
actions: actions,
source: TestDataSource(onSelectChanged: (bool? value) {}),
showCheckboxColumn: true,
columns: const <DataColumn>[
DataColumn(label: Text('Name')),
DataColumn(label: Text('Calories'), numeric: true),
DataColumn(label: Text('Generation')),
],
),
);
await tester.pumpWidget(buildTable(header: headerText));
expect(find.text(headerText), findsOneWidget);
expect(find.byIcon(Icons.add), findsNothing);
await tester.pumpWidget(buildTable(header: headerText, actions: actions));
expect(find.text(headerText), findsOneWidget);
expect(find.byIcon(Icons.add), findsOneWidget);
await tester.pumpWidget(buildTable());
expect(find.text(headerText), findsNothing);
expect(find.byIcon(Icons.add), findsNothing);
expect(() => buildTable(actions: actions), throwsAssertionError);
await binding.setSurfaceSize(null);
});
testWidgets('PaginatedDataTable with large text', (WidgetTester tester) async {
final TestDataSource source = TestDataSource();
await tester.pumpWidget(MaterialApp(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment