We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Editing of filtered data in pagination does not work properly. Other issues with pagination

I enabled editing, pagination, and filtering (via UI) in SFDataGrid. I didn't override handlePageChange in order for sorting and filtering to be done for the whole set of rows. I have 5 rows per page.

My data consists of 8 records: 5 records on page 1 and 3 records on page 2.

There are 2 issues.

  1. When I go to page 2, I edit the 3rd record on page 2. When editing is done, 3rd record on page 1 is updated instead, which is very dangerous. I looked at onCellSubmit(DatagridRow dataGridRow.....) function and dataGridRow actually is 3rd record of page 1. This is wrong. I had to write a workaround that takes into consideration a current page in order to retrieve a proper row from dataGridRows. buildEditWidget has actually a correct row. This needs to get fixed
  2. When I manually filter data and try to edit any cell after that, exceptions will occur and the row will be gone from the DataGrid completely. I can't find a workaround for that issue. Here is an exception below. I noticed however that when data is filtered  onCellSubmit(DatagridRow dataGridRow.....)  returns correct  dataGridRow. 

E/flutter (22765): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: RangeError (index): Invalid value: Valid value range is empty: 0

E/flutter (22765): #0 List.[] (dart:core-patch/growable_array.dart:264:36)

E/flutter (22765): #1 SfDataGridState._processCellUpdate

package:syncfusion_flutter_datagrid/…/datagrid_widget/sfdatagrid.dart:1903

E/flutter (22765): #2 SfDataGridState._handleDataGridPropertyChangeListeners

package:syncfusion_flutter_datagrid/…/datagrid_widget/sfdatagrid.dart:2230

E/flutter (22765): #3 DataGridSourceChangeNotifier._notifyDataGridPropertyChangeListeners

package:syncfusion_flutter_datagrid/…/datagrid_widget/sfdatagrid.dart:4191

E/flutter (22765): #4 notifyDataGridPropertyChangeListeners

package:syncfusion_flutter_datagrid/…/datagrid_widget/sfdatagrid.dart:4205

E/flutter (22765): #5 CurrentCellManager.onCellSubmit

package:syncfusion_flutter_datagrid/…/selection/selection_manager.dart:1939

E/flutter (22765): #6 CurrentCellManager.onCellBeginEdit.submitCell

package:syncfusion_flutter_datagrid/…/selection/selection_manager.dart:1792

E/flutter (22765): #7 StudentDataSource.buildEditWidget.<anonymous closure>

package:drivingschool/datasource/student_data_source.dart:331

E/flutter (22765): <asynchronous suspension>

E/flutter (22765):

I/IMM_LC (22765): hsifw() - flag : 0

I/IMM_LC (22765): hsifw() - mService.hideSoftInput

D/InsetsController(22765): controlAnimationUnchecked: Added types=8 animType=1 host=team.cdl.drivingschool/team.cdl.drivingschool.MainActivity from=android.view.InsetsController.applyAnimation:1576 android.view.InsetsController.applyAnimation:1557 android.view.InsetsController.hide:1093


9 Replies

IG Igor December 29, 2022 02:50 AM UTC

Here is some code snapshots for the issues above

---------------------------------------------------------

class StudentDataSource extends DataGridSource {

  StudentDataSource() {

    buildDataGridRows();

  }

  List<Student> _students = [];

  List<DataGridRow> dataGridRows = [];

  //Map<String, Student> _studentsMap = {};

  dynamic newCellValue;

  TextEditingController editingController = TextEditingController();

  DataPagerController pageController = DataPagerController();


  // pagination logic

  final double _dataPagerHeight = 60.0;

  int _rowsPerPage = 5;


  void buildDataGridRows() {

    dataGridRows = _students.map<DataGridRow>((student) => student.getDataGridRow()).toList();

  }


  double getPageCount() {

    double pageCount = _students.isEmpty ? 1 : (_students.length / _rowsPerPage).ceil() * 1.0;

    return pageCount;

  }


  void updateDataGridSource() {

    notifyListeners();

  }


@override

void onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async {

final int pageAdjustment = pageController.selectedPageIndex * _rowsPerPage; // _rowsPerPage = 5;

      final int dataRowIndex = isAnyFilterEnabled() ? dataGridRows.indexOf(dataGridRow) : pageAdjustment + rowColumnIndex.rowIndex;

if (dataRowIndex < dataGridRows.length) {

DataGridRow curGridRow = dataGridRows[dataRowIndex];

dynamic oldValue;

for (var cell in curGridRow.getCells()) {

if (column.columnName == cell.columnName) {

oldValue = cell.value ?? '';

}

}

if (newCellValue == null || oldValue == newCellValue) return;

if (column.columnName == Student.colId) {

dataGridRows[dataRowIndex].getCells()[rowColumnIndex.columnIndex] =

             DataGridCell<String>(columnName: column.columnName, value: newCellValue);

           _students[dataRowIndex].id = newCellValue.toString();

} else if .......

... save data in backend

}

}


@override

bool canSubmitCell(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) {

    return true; // Return false, to retain in edit mode; or super.canSubmitCell(dataGridRow, rowColumnIndex, column);

}


@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() ??

        '';

    newCellValue = null;

    ...

    return Container(

      padding: const EdgeInsets.all(5.0),

      alignment: isNumericType ? Alignment.centerRight : Alignment.centerLeft,

      child: TextField(

        autofocus: true,

        controller: editingController..text = displayText,

        textAlign: isNumericType ? TextAlign.right : TextAlign.left,

        decoration: const InputDecoration(

          contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 5.0),

          //errorText: errText,

        ),

        inputFormatters: customFormatters,

        keyboardType: keyboardType,

        onChanged: (String value) {

          if (value.isNotEmpty) {

            if (isNumericType) {

              newCellValue = int.parse(value);

            } else {

              newCellValue = value;

            }

          } else {

            newCellValue = null;

          }

        },

        onSubmitted: (String value) async {

          bool isValidated = await validateField(context!, column.columnName, value);

          if (isValidated) {

            //try {

            submitCell();

            //} catch (e) {

            //devtools.log("Caught Exception ${e.toString()}");

            //}

          } else {

            editingController.text = displayText;

          }

        },

      ),

    );

  }


// VIEW

class _StudentsViewState extends State<StudentsView> {

  late StudentDataSource _studentDataSource;

  late DataGridController _dataGridController;

  ......

  void initState() {

    _studentDataSource = StudentDataSource();

    _dataGridController = DataGridController();

    super.initState();

  }


  @override

  Widget build(BuildContext context) {

  ......

      return Column(

                      children: [

                        SizedBox(

                          height: constraint.maxHeight - _studentDataSource.dataPagerHeight,

                          width: constraint.maxWidth,

                          child: SfDataGridTheme(

                            data: SfDataGridThemeData(

                              headerColor: const Color.fromARGB(255, 250, 235, 208),

                              headerHoverColor: const Color.fromARGB(255, 226, 250, 248), // for web

                            ),

                            child: SfDataGrid(

                                source: _studentDataSource,

                                allowFiltering: true,

                                allowSorting: true,

                                allowTriStateSorting: true,

                                selectionMode: SelectionMode.single,

                                defaultColumnWidth: 137,

                                headerGridLinesVisibility: GridLinesVisibility.both,

                                gridLinesVisibility: GridLinesVisibility.both,

                                allowEditing: true,

                                navigationMode: GridNavigationMode.cell,

                                editingGestureType: EditingGestureType.doubleTap,

                                controller: _dataGridController,

                                columns: getStudentColumns(),

                                allowSwiping: true,

                                rowsPerPage: _studentDataSource.rowsPerPage,

                                onFilterChanged: (DataGridFilterChangeDetails details) =>

                                    _studentDataSource.filterChanged(details)),

                          ),

                        ),


                        // ignore: sized_box_for_whitespace

                        Container(

                            height: _studentDataSource.dataPagerHeight,

                            child: SfDataPager(

                              delegate: _studentDataSource,

                              pageCount: _studentDataSource.getPageCount(),

                              controller: _studentDataSource.pageController,

                              direction: Axis.horizontal,


                            ))

                      ],

                    );

......



TP Tamilarasan Paranthaman Syncfusion Team December 30, 2022 01:01 PM UTC

Hi Igor,


Regarding: When I go to page 2, I edit the 3rd record on page 2. When editing is done, 3rd record on page 1 is updated instead, which is very dangerous.


Can please let us know, whether you are generating the DataGridRow only for the current page by overriding handlePageChange in DataGridSource or creating DataGrid with the whole underlying collection?


Regarding: When I manually filter data and try to edit any cell after that, exceptions will occur and the row will be gone from the DataGrid completely.


We are checking this at our end. We will check and let you know about this issue.


Regards,

Tamilarasan



IG Igor December 30, 2022 06:24 PM UTC

Hi Tamilarasan,


Here is my answer:

Can please let us know, whether you are generating the DataGridRow only for the current page by overriding handlePageChange in DataGridSource or creating DataGrid with the whole underlying collection?

I do not override handlePageChange in DataGridSource as mentioned in the very first thread. I generate DataGrid for the whole underlying collection. For that, I use a StreamBuilder to retrieve data from the Firebase cloud store. So in this case, the whole collection (currently 8 records only) is already available before DataGrid is rendered. Here is the code for review below

Thanks,

Igor



class StudentsViewState extends State<StudentsView> {
  late StudentDataSource _studentDataSource;
  late DataGridController _dataGridController;

  @override
  void initState() {
    _studentDataSource = StudentDataSource();
    _dataGridController = DataGridController();
_studentDataSource.setStudentViewState(this);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
        stream: FirebaseCloudStorage().getStudentsData(),
        builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
          _studentDataSource.setBuildContext(context);
          if (snapshot.hasData) {
            if (_studentDataSource.students.isNotEmpty) {
              bool hasChange = false;
              for (var data in snapshot.data!.docChanges) {
                Student student = Student.fromFirestoreDocumentChange(data);
                if (data.type == DocumentChangeType.modified) {
                  if (data.oldIndex == data.newIndex) {
                    hasChange = true;
// if (index < _students.length) _students[index] = student;
                    _studentDataSource.updateStudentRecord(data.oldIndex, student);
                  }
                } else if (data.type == DocumentChangeType.added) {
                  hasChange = true;
// _students.insert(0, student);
                  _studentDataSource.insertStudentRecord(student);
                } else if (data.type == DocumentChangeType.removed) {
                  hasChange = true;
// if (index < _students.length) _students.removeAt(index);
                  _studentDataSource.removeStudentRecord(data.oldIndex);
                }
              }
              if (hasChange) { // hasChange likely won't be needed cause snapshot.hasData = true;
// dataGridRows = _students.map<DataGridRow>((student) => student.getDataGridRow()).toList();
                _studentDataSource.buildDataGridRows();
// notifyListeners();
                _studentDataSource.updateDataGridSource();
              }
            } else {
              for (var data in snapshot.data!.docs) {
                _studentDataSource.addStudentRecord(
                  Student.fromFirestoreQueryDocumentSnapshot(data),
                ); // _students.add(student);
              }
              _studentDataSource.buildDataGridRows();
              _studentDataSource.updateDataGridSource();
            }
          }
          return SafeArea(
            child: Scaffold(
                appBar: getAppBar(context),
                body: LayoutBuilder(
                  builder: (context, constraint) {
                    return Column(
                      children: [
                        SizedBox(
                          height: constraint.maxHeight - _studentDataSource.dataPagerHeight,
                          width: constraint.maxWidth,
                          child: SfDataGridTheme(
                            data: SfDataGridThemeData(
                              headerColor: const Color.fromARGB(255, 250, 235, 208),
                              headerHoverColor: const Color.fromARGB(255, 226, 250, 248), // for web
                            ),
                            child: SfDataGrid(
                                source: _studentDataSource,
                                allowFiltering: true,
                                allowSorting: true,
                                allowTriStateSorting: true,
                                selectionMode: SelectionMode.single,
                                defaultColumnWidth: 137,
                                headerGridLinesVisibility: GridLinesVisibility.both,
                                gridLinesVisibility: GridLinesVisibility.both,
                                allowEditing: true,
                                navigationMode: GridNavigationMode.cell,
                                editingGestureType: EditingGestureType.doubleTap,
                                controller: _dataGridController,
                                columns: getStudentColumns(),
                                allowSwiping: true,
                                rowsPerPage: _studentDataSource.rowsPerPage, // for now rowsPerPage = 5
                                onFilterChanged: (DataGridFilterChangeDetails details) =>
                                    _studentDataSource.filterChanged(details)),
                          ),
                        ),

                        // ignore: sized_box_for_whitespace
                        Container(
                            height: _studentDataSource.dataPagerHeight,
                            child: SfDataPager(
                              delegate: _studentDataSource,
                              pageCount: _studentDataSource.getPageCount(),
                              controller: _studentDataSource.pageController,
                              direction: Axis.horizontal,
                            ))
                      ],
                    );
                  },
                )),
          );
        });
  }

class StudentDataSource extends DataGridSource {
  StudentDataSource() {
    buildDataGridRows();
  }

  // ignore: prefer_final_fields
  List<Student> _students = [];
  List<DataGridRow> dataGridRows = [];
  dynamic newCellValue;
  TextEditingController editingController = TextEditingController();
  DataPagerController pageController = DataPagerController();

  // pagination logic
  final double _dataPagerHeight = 60.0;
  int _rowsPerPage = 5; // let's try to use platform, i.e. for web it will be more than mobile

  // for pagination/filtering bug workaround
  BuildContext? context;
  Map<String, DataGridFilterChangeDetails> filteredEnabledMap = {};
  int buildEditWidgetIndex = -1;
  StudentsViewState? state;

  void buildDataGridRows() {
    dataGridRows = _students.map<DataGridRow>((student) => student.getDataGridRow()).toList();
  }

  @override
  List<DataGridRow> get rows => dataGridRows;

  void updateDataGridSource() {
    notifyListeners();
  }

  void insertStudentRecord(final Student student) {
    _students.insert(0, student);
  }

  void removeStudentRecord(final int index) {
    if (index < _students.length) {
      _students.removeAt(index);
    }
  }

  void updateStudentRecord(final int index, final Student student) {
    if (index < _students.length) {
      _students[index] = student;
    }
  }

  void addStudentRecord(final Student student) {
    _students.add(student);
  }

  List<Student> get students => _students;

  @override
  DataGridRowAdapter? buildRow(DataGridRow row) {
    return DataGridRowAdapter(
        cells: row.getCells().map<Widget>((dataGridCell) {
      return Container(
        // swidth: 100, //color: const Color.fromARGB(255, 227, 229, 230),
        padding: EdgeInsets.symmetric(horizontal: ((dataGridCell.columnName == 'whateverColumn') ? 10 : 5)),
        alignment: Alignment.centerLeft,
        child: Text(
          dataGridCell.value.toString(),
          overflow: TextOverflow.fade,
        ),
      );
    }).toList());
  }

  @override
  void onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async {
  void onCellSubmit(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) async {
    // ========= BUG for paging/filtering:
// In buildEditWidget Function dataGridRows.indexOf(dataGridRow) returns correct index, here is not.
// we will retrieve index from buildEditWidget function
    int curRowIndex = dataGridRows.indexOf(dataGridRow);
    final int dataRowIndex = (curRowIndex != buildEditWidgetIndex) ? buildEditWidgetIndex : curRowIndex;
    if (dataRowIndex < dataGridRows.length) {
      DataGridRow curGridRow = dataGridRows[dataRowIndex];
      dynamic oldValue;
      dynamic licenseNo;
      for (var cell in curGridRow.getCells()) {
        if (cell.columnName == Student.colLicenseNumber) {
          licenseNo = cell.value ?? '';
        }
        if (column.columnName == cell.columnName) {
          oldValue = cell.value ?? '';
        }
      }

      if (newCellValue == null || oldValue == newCellValue) return;
      if (column.columnName == Student.colLicenseNumber) {
        dataGridRows[dataRowIndex].getCells()[rowColumnIndex.columnIndex] =
            DataGridCell<int>(columnName: column.columnName, value: newCellValue);
        _students[dataRowIndex].licenseNumber = newCellValue as int;
      }
....... setting up other columns
      Student? student = getStudent(oldValue, licenseNo);
      if (student != null) {
........ updating student record with newCellValue and posting audit for oldValue
      }
    }
  }

  @override
  Widget? buildEditWidget(
      DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column, CellSubmit submitCell) {
    final String displayText = dataGridRow
            .getCells()
            .firstWhereOrNull((DataGridCell dataGridCell) => dataGridCell.columnName == column.columnName)
            ?.value
            ?.toString() ??
        '';

    buildEditWidgetIndex = dataGridRows.indexOf(dataGridRow);
    newCellValue = null;
    final bool isNumericType = column.columnName == Student.colLicenseNumber;
    var keyboardType = TextInputType.text;
    final List<TextInputFormatter> maxLenFmt = <TextInputFormatter>[LengthLimitingTextInputFormatter(100)];
    var customFormatters = <TextInputFormatter>[];
..... setting up input formatters and keyboard type for each field
.....
    return Container(
      padding: const EdgeInsets.all(5.0),
      alignment: isNumericType ? Alignment.centerRight : Alignment.centerLeft,
      child: TextField(
        autofocus: true,
        controller: editingController..text = displayText,
        textAlign: isNumericType ? TextAlign.right : TextAlign.left,
        decoration: const InputDecoration(
          contentPadding: EdgeInsets.fromLTRB(0, 0, 0, 5.0),
          //errorText: errText,
        ),
        inputFormatters: customFormatters,
        keyboardType: keyboardType,
        onChanged: (String value) {
          if (value.isNotEmpty) {
            if (isNumericType) {
              newCellValue = int.parse(value);
            } else {
              newCellValue = value;
            }
          } else {
            newCellValue = null;
          }
        },
        onSubmitted: (String value) async {
          bool isValidated = await validateField(context!, column.columnName, value);
          if (isValidated) {
            try { // NEED TRY /CATCH DUE TO EXCEPTION WHEN EDITING FILTERED ROW
              submitCell();
            } catch (e) {
// WORKAROUND: REFRESH SCREENS, BUT IT IS A BAD SOLUTION
              Navigator.of(context!).popUntil((studentsRoute) => false);
              StudentsView studentsView = const StudentsView();
              await Navigator.push(
                context!,
                MaterialPageRoute(builder: (context) => studentsView),
              );
            }
          } else {
            editingController.text = displayText;
          }
        },
      ),
    );
  }

  @override
  bool canSubmitCell(DataGridRow dataGridRow, RowColumnIndex rowColumnIndex, GridColumn column) {
    return true; // Return false, to retain in edit mode; or super.canSubmitCell(dataGridRow, rowColumnIndex, column);
  }

  Student? getStudent(final dynamic oldValue, final dynamic licenseNo) {
..... retrieving student record from students
  }

  double getPageCount() {
    double pageCount = _students.isEmpty ? 1 : (_students.length / _rowsPerPage).ceil() * 1.0;
    //devtools.log(" \n\n _students.length ${_students.length} pageCount $pageCount \n\n ");
    return pageCount;
  }

  void setStudentViewState(StudentsViewState s) {
    state = s;
  }

  setBuildContext(BuildContext? ctx) {
    context = ctx;
  }

  double get dataPagerHeight => _dataPagerHeight;

  int get rowsPerPage => _rowsPerPage;

  void setRowsPerPage(int numRows) {
    _rowsPerPage = numRows;
  }


TP Tamilarasan Paranthaman Syncfusion Team January 5, 2023 01:07 PM UTC

Hi Igor,


We have validated the reported issues, and we are able to replicate both issue at our end. We have considered this as a bug and logged a bug report in our feedback portal. We will fix the reported issue and include the changes in our upcoming weekly patch release, which is expected to be rolled out on January 10, 2022. We will let you know once it is published. We appreciate your patience and understanding until then.


Feedback Link: https://www.syncfusion.com/feedback/40215/editing-of-filtered-data-when-paging-is-applied-does-not-work-properly


Regards,

Tamilarasan



IG Igor January 5, 2023 05:19 PM UTC

Thanks for the feedback.


Regards,

Igor



TP Tamilarasan Paranthaman Syncfusion Team January 10, 2023 09:29 AM UTC

Igor, the fix for the reported issue “Editing of filtered data in pagination does not work properly” has been included in the latest DataGrid version 20.4.43. Update your DataGrid to get the issue resolved.



IG Igor January 11, 2023 12:58 AM UTC

Thank you. Looks like that behavior is fixed but I haven't deeply tested it yet.

 I found another bug, or please let me know if there is a solution to the following:

On the grid, my filtering is enabled. When I add some filter to the column by hand, SFDataPager.pageCount property is updated via _studentDataSource.getPageCount() and changes are reflected on the screen - see code below. This is good and the correct number of pages is shown on the SfDataPager. However, once I clear the filter from the same column by hand, SFDataPager.pageCount property IS NOT updated, i.e. _studentDataSource.getPageCount()  is not called causing the screen to show incorrect page numbers.

Workaround looks ugly so far. I think you have to ensure that internally sfDataPager._pageCount is updated when the filter is cleared on any column. It also will be a great idea to have a method allowing updating pageCount from datasource and those changes reflected on the screen.

Please let me know if I missed anything or is there a way to make that work properly

Kind Regards,

Igor


Container(
                            height: _studentDataSource.dataPagerHeight,
                            child: SfDataPager(
                              delegate: _studentDataSource,
                              pageCount: _studentDataSource.getPageCount(),
                              controller: _studentDataSource.pageController,
                              direction: Axis.horizontal,
                              onPageNavigationEnd: (pageIndex) {
                               
                              },
                            ))
                      ],

--------- student_data_source.dart
  double getPageCount() {
    return effectiveRows.isEmpty ? 1 : (effectiveRows.length / _rowsPerPage).ceil() * 1.0;
  }



TP Tamilarasan Paranthaman Syncfusion Team January 11, 2023 11:11 AM UTC

Igor,


Based on the information you've provided, it appears that the solution to this issue involves updating the page count in the SfDataGrid.onFilterChanged callback. We have previously shared a sample that demonstrates this approach and have also provided a code snippet as an example. We recommend that you review the shared sample and code snippet and compare them to your implementation to ensure that they are identical.


  void _updatePageCount() {

    final rowsCount = _employeeDataSource.filterConditions.isNotEmpty

        ? _employeeDataSource.effectiveRows.length

        : employees.length;

    pageCount = (rowsCount / _rowsPerPage).ceilToDouble();

  }

 

  @override

  void initState() {

    super.initState();

    _employeeDataSource = EmployeeDataSource();

    _updatePageCount();

  }

 

  @override

  Widget build(BuildContext context) {

    return Scaffold(

        appBar: AppBar(title: const Text('PageNavigation Demo')),

        body: LayoutBuilder(builder: (context, constraints) {

          return Column(children: [

            SizedBox(

                height: constraints.maxHeight - 60,

                child: SfDataGrid(

                    allowFiltering: true,

                    onFilterChanged: (details) {

                      setState(() {

                        _updatePageCount();

                      });

                    },

                    source: _employeeDataSource,

                    columnWidthMode: ColumnWidthMode.fill,

                    columns: getColumns)),

            SizedBox(

              height: 60,

              child: SfDataPager(

                  pageCount: pageCount, delegate: _employeeDataSource),

            ),

          ]);

        }));

  }




IG Igor replied to Tamilarasan Paranthaman January 11, 2023 09:07 PM UTC

Hi Tamil,


I made something similar in my code using onFilterChanged but I thought it was a workaround due to the need to call setState(). setState() will trigger a refresh causing a call to the server to retrieve data (via StreamBuilder) which I want to avoid. In order not to make the server call, you will need to introduce a set of variables that will keep track of whether it was a filter change or not and make a server call or not. And this whole thing needs to be done simply to reflect a correct page number for the filtered set of data.


Thanks for the heads up though. I will keep it this way for now. If you introduce other ways to handle page number refresh, please let me know.


Regards,

Igor


Loader.
Live Chat Icon For mobile
Up arrow icon