Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter PaginatedDataTable rowsPerPage

Tags:

flutter

dart

Can flutter PaginatedDataTable rowsPerPage be set to a number not divisible by 10?

UPDATE

Data used by the FutureBuilder is fetched from a local server. At first, the list contains 3 items which results into empty DataRows being created.

My Problem

  1. I don't want the empty DataRows to be created

What I've Tried

  1. Setting the rowsPerPage count to the length of the list IF the list-length is less than the defaultRowsPerPage ELSE set it (rowsPerPage) to defaultRowsPerPage.

SAMPLE CODE

import 'package:flutter/material.dart';
import 'package:nvip/constants.dart';
import 'package:nvip/data_repo/network/centers_repo.dart';
import 'package:nvip/data_repo/tables/data_source_centers.dart';
import 'package:nvip/models/vaccination_center.dart';

class VaccinationCentersTableScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) => _CentersScreenBody();
}

class _CentersScreenBody extends StatefulWidget {
  @override
  __CentersScreenBodyState createState() => __CentersScreenBodyState();
}

class __CentersScreenBodyState extends State<_CentersScreenBody> {
  int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage; // This one works
  int _columnIndex = 1;
  bool _isSortAscending = true;
  Future<List<VaccineCenter>> _centers;
  CentersTableDataSource _tableDataSource;
  var _scaffoldKey = GlobalKey<ScaffoldState>();

  void _sort<T>(Comparable<T> getField(VaccineCenter c), int columnIndex,
      bool isSortAscending) {
    _tableDataSource?.sort(getField, isSortAscending);
    setState(() {
      _columnIndex = columnIndex;
      _isSortAscending = isSortAscending;
    });
  }

  @override
  void initState() {
    super.initState();
    _centers = VaccineCentersDataRepo().getCenters();
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () {
        Navigator.pushReplacementNamed(context, Routes.keyHome);
      },
      child: Scaffold(
        key: _scaffoldKey,
        appBar: AppBar(
          title: Text("Vaccination Centers"),
          centerTitle: true,
          leading: IconButton(
            icon: Icon(Constants.backIcon),
            onPressed: () {
              Navigator.pushReplacementNamed(context, Routes.keyHome);
            },
          ),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.add),
              tooltip: "Add vaccination center",
              onPressed: () {
                Navigator.pushReplacementNamed(context, Routes.keyPovAdd);
              },
            )
          ],
        ),
        body: FutureBuilder<List<VaccineCenter>>(
          future: _centers,
          builder: (context, snapshot) {
            if (snapshot.hasError) {
              return Constants.showHasNoDataWidget(
                context,
                "No vaccination center(s) / place(s) of vaccinations found. "
                    "Press the (+) sign to add a new record.",
              );
            } else {
              if (snapshot.hasData) {
                var centerList = snapshot.data;
                var centersCount = centerList.length;
                var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;
                _rowsPerPage = centersCount < defaultRowsPerPage
                    ? centersCount
                    : defaultRowsPerPage;
                _tableDataSource = CentersTableDataSource(centerList);
                return SingleChildScrollView(
                  child: PaginatedDataTable(
                    header: Text("Places of Vaccination"),
                    rowsPerPage: _rowsPerPage,
                    onRowsPerPageChanged: (rowCount) {
                      setState(() {
                        _rowsPerPage = rowCount;
                      });
                    },
                    sortColumnIndex: _columnIndex,
                    sortAscending: _isSortAscending,
                    onSelectAll: (isAllChecked) =>
                        _tableDataSource?.selectAll(isAllChecked),
                    actions: <Widget>[
                      IconButton(
                        icon: Icon(Icons.add),
                        tooltip: "Add vaccination center",
                        onPressed: () {
                          Navigator.pushReplacementNamed(
                              context, Routes.keyPovAdd);
                        },
                      ),
                      IconButton(
                        icon: Icon(Icons.delete_forever),
                        tooltip: "Delete vaccination center(s).",
                        onPressed: () {
                          Constants.showSnackBar(
                              _scaffoldKey, "Delete button clicked");
                        },
                      )
                    ],
                    columns: <DataColumn>[
                      DataColumn(
                        label: Text("No."),
                        numeric: true,
                        onSort: (ci, isSortAscending) => _sort<num>(
                            (c) => centerList.indexOf(c), ci, isSortAscending),
                      ),
                      DataColumn(
                        label: Text("Name"),
                        onSort: (ci, isSortAscending) =>
                            _sort<String>((c) => c.name, ci, isSortAscending),
                      ),
                    ],
                    source: _tableDataSource,
                  ),
                );
              }
            }

            return Center(child: CircularProgressIndicator());
          },
        ),
      ),
    );
  }
}

ERROR LOG

I/flutter ( 8474): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 8474): The following assertion was thrown building FutureBuilder<List<VaccineCenter>>(dirty, state:
I/flutter ( 8474): _FutureBuilderState<List<VaccineCenter>>#92379):
I/flutter ( 8474): 'package:flutter/src/material/paginated_data_table.dart': Failed assertion: line 87 pos 19:
I/flutter ( 8474): 'availableRowsPerPage != null && availableRowsPerPage.contains(rowsPerPage)': is not true.
I/flutter ( 8474): 
I/flutter ( 8474): Either the assertion indicates an error in the framework itself, or we should provide substantially
I/flutter ( 8474): more information in this error message to help you determine and fix the underlying cause.
I/flutter ( 8474): In either case, please report this assertion by filing a bug on GitHub:
I/flutter ( 8474):   https://github.com/flutter/flutter/issues/new?template=BUG.md
I/flutter ( 8474): 
I/flutter ( 8474): When the exception was thrown, this was the stack:
I/flutter ( 8474): #2      new PaginatedDataTable.<anonymous closure> (package:flutter/src/material/paginated_data_table.dart:87:19)
I/flutter ( 8474): #3      new PaginatedDataTable (package:flutter/src/material/paginated_data_table.dart:89:9)
I/flutter ( 8474): #4      __CentersScreenBodyState.build.<anonymous closure> (package:nvip/scenes/vaccination_centers/screen_center_table.dart:86:26)
I/flutter ( 8474): #5      _FutureBuilderState.build (package:flutter/src/widgets/async.dart)
I/flutter ( 8474): #6      StatefulElement.build (package:flutter/src/widgets/framework.dart:3809:27)
I/flutter ( 8474): #7      ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:3721:15)
I/flutter ( 8474): #8      Element.rebuild (package:flutter/src/widgets/framework.dart:3547:5)
I/flutter ( 8474): #9      BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2286:33)
I/flutter ( 8474): #10     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding&WidgetsBinding.drawFrame (package:flutter/src/widgets/binding.dart:676:20)
I/flutter ( 8474): #11     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding&PaintingBinding&SemanticsBinding&RendererBinding._handlePersistentFrameCallback (package:flutter/src/rendering/binding.dart:219:5)
I/flutter ( 8474): #12     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._invokeFrameCallback (package:flutter/src/scheduler/binding.dart:990:15)
I/flutter ( 8474): #13     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding.handleDrawFrame (package:flutter/src/scheduler/binding.dart:930:9)
I/flutter ( 8474): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&SchedulerBinding._handleDrawFrame (package:flutter/src/scheduler/binding.dart:842:5)
I/flutter ( 8474): #15     _invoke (dart:ui/hooks.dart:154:13)
I/flutter ( 8474): #16     _drawFrame (dart:ui/hooks.dart:143:3)
I/flutter ( 8474): (elided 2 frames from class _AssertionError)
I/flutter ( 8474): ════════════════════════════════════════════════════════════════════════════════════════════════════

UPDATE 2

My DataTableSource

import 'package:flutter/material.dart';
import 'package:nvip/models/vaccination_center.dart';

class CentersTableDataSource extends DataTableSource {
  final List<VaccineCenter> _centers;
  int _rowsSelectedCount = 0;

  CentersTableDataSource(this._centers);

  @override
  DataRow getRow(int index) {
    assert(index >= 0);
    if (index >= _centers.length) return null;
    final VaccineCenter center = _centers[index];
    return DataRow.byIndex(
      index: index,
      selected: center.isSelected,
      onSelectChanged: (selected) {
        if (center.isSelected != selected) {
          _rowsSelectedCount += selected ? 1 : -1;
          center.isSelected = selected;
          notifyListeners();
        }
      },
      cells: <DataCell>[
        DataCell(Text("${index + 1}")),
        DataCell(Text(center.name)),
      ],
    );
  }

  @override
  bool get isRowCountApproximate => false;

  @override
  int get rowCount => _centers.length;

  @override
  int get selectedRowCount => _rowsSelectedCount;

  void sort<T extends Object>(
      Comparable<T> getField(VaccineCenter d), bool isAscending) {
    _centers.sort((a, b) {
      if (isAscending) {
        final VaccineCenter c = a;
        a = b;
        b = c;
      }

      final Comparable<T> aValue = getField(a);
      final Comparable<T> bValue = getField(b);
      return Comparable.compare(aValue, bValue);
    });
    notifyListeners();
  }

  void selectAll(bool isAllChecked) {
    _centers.forEach((center) => center.isSelected = isAllChecked);
    _rowsSelectedCount = isAllChecked ? _centers.length : 0;
    notifyListeners();
  }
}
like image 881
Mitch Avatar asked Jan 26 '19 07:01

Mitch


2 Answers

  import 'package:flutter/material.dart';

    class DemoTable extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return _DemoTableBody();
      }
    }

    class _DemoTableBody extends StatefulWidget {
      @override
      __DemoTableBodyState createState() => __DemoTableBodyState();
    }

    class __DemoTableBodyState extends State<_DemoTableBody> {

      int _rowsPerPage = PaginatedDataTable.defaultRowsPerPage;

      // A Variable to hold the length of table based on the condition of comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage

      int _rowsPerPage1 = PaginatedDataTable.defaultRowsPerPage;

      @override
      Widget build(BuildContext context) {

      //Obtain the data to be displayed from the Derived DataTableSource

        var dts = DTS(); 

        // dts.rowcount provides the actual data length, ForInstance, If we have 7 data stored in the DataTableSource Object, then we will get 12 as dts.rowCount

       var tableItemsCount = dts.rowCount; 

        // PaginatedDataTable.defaultRowsPerPage provides value as 10

        var defaultRowsPerPage = PaginatedDataTable.defaultRowsPerPage;

        // We are checking whether tablesItemCount is less than the defaultRowsPerPage which means we are actually checking the length of the data in DataTableSource with default PaginatedDataTable.defaultRowsPerPage i.e, 10

        var isRowCountLessDefaultRowsPerPage = tableItemsCount < defaultRowsPerPage;

        // Assigning rowsPerPage as 10 or acutal length of our data in stored in the DataTableSource Object

        _rowsPerPage =
            isRowCountLessDefaultRowsPerPage ? tableItemsCount : defaultRowsPerPage;
        return Scaffold(
          appBar: AppBar(
            title: Text("Demo Paginated Table"),
          ),
          body: SingleChildScrollView(
            child: PaginatedDataTable(
              header: Text('data with 7 rows per page'),
              // comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage and then assigning it to _rowPerPage1 variable which then set using the setsState()
              onRowsPerPageChanged: isRowCountLessDefaultRowsPerPage // The source of problem!
                  ? null
                  : (rowCount) {
                      setState(() {
                        _rowsPerPage1 = rowCount;
                      });
                    },
              columns: <DataColumn>[
                DataColumn(label: Text('row')),
                DataColumn(label: Text('name')),
              ],
              source: dts,
              //Set Value for rowsPerPage based on comparing the actual data length with the PaginatedDataTable.defaultRowsPerPage 
              rowsPerPage:
                  isRowCountLessDefaultRowsPerPage ? _rowsPerPage : _rowsPerPage1,
            ),
          ),
        );
      }
    }

    class DTS extends DataTableSource {
      @override
      DataRow getRow(int index) {
        return DataRow.byIndex(
          index: index,
          cells: [
            DataCell(Text('row #$index')),
            DataCell(Text('name #$index')),
          ],
        );
      }

      @override
      int get rowCount => 9; // Manipulate this to which ever value you wish

      @override
      bool get isRowCountApproximate => false;

      @override
      int get selectedRowCount => 0;
    }
like image 103
Mitch Avatar answered Nov 15 '22 08:11

Mitch


This error is caused by the values provided by flutter. rowsPerPage can only be 10, 20, 50 and 100.

snapshot source PaginatedDataTable

This is specified in the source PaginatedDataTable.

like image 31
IERomanov Avatar answered Nov 15 '22 10:11

IERomanov