pluto_grid icon indicating copy to clipboard operation
pluto_grid copied to clipboard

setCreateFooter(callback) has not effect [Bug]

Open elgsylvain85 opened this issue 3 years ago • 1 comments

Steps to reproduce the bug

I tried ".setCreateFooter(state)" to dynamically update the Widget returned by "createFooter" but seems to have no effect. The idea for me is to have a custom pagination panel as I am loading table data incrementally.

Expected results

PlutoGrid return the new Footer Widget

Actual results

Keep displaying the Widget predefined with "createFooter"

Code sample

build(context)

PlutoGrid(
              columns: dataColumns(),
              rows: [],
              onLoaded: (event) {
                widget.dataTableStateManager = event.stateManager;
                refreshDataTable();
              },
              createFooter: (stateManager) {
                return dataTableFooter();
              },
            )

Method dataTableFooter()

Widget dataTableFooter() {
  
      final totalPages = (widget.totalDataCount / widget.rowsPerPage).ceil();
  
      final currentPage = (widget.offset ~/ widget.rowsPerPage) + 1;
      List<int> pageList = [];
      if (currentPage > 1) {
        pageList.addAll(
          List.generate(currentPage - 1, (index) => index + 1),
        );
        //Keep up to 3 pages before current in the list
        pageList.removeWhere(
          (element) => element < currentPage - maxPagesBeforeCurrent,
        );
      }
      pageList.add(currentPage);
      //Add reminding pages after current to the list
      pageList.addAll(
        List.generate(
          maxPagesToShow - (pageList.length - 1),
          (index) => (currentPage + 1) + index,
        ),
      );
      pageList.removeWhere((element) => element > totalPages);
  
      return Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: pageList
            .map(
              (e) => TextButton(
                onPressed: e != currentPage
                    ? () {
                        // load data according offset
                      }
                    : null,
                child: Text(
                  e.toString(),
                ),
              ),
            )
            .toList(),
      );
    }

Method refreshDataTable()

void refreshDataTable() {
    widget.dataTableStateManager?.setShowLoading(true);
    PlutoGridStateManager.initializeRowsAsync(
      dataColumns(),
      dataRows(widget.dataList),
    ).then((value) {
      widget.dataTableStateManager?.refRows.clear();
      widget.dataTableStateManager?.refRows
          .addAll(FilteredList(initialList: value));
      widget.dataTableStateManager?.setCreateFooter((stateManager) {
        return dataTableFooter();
      });
      widget.dataTableStateManager?.setShowLoading(false);

      setState(() {});
    }).catchError((e, s) {
      log("$e", stackTrace: s);

      widget.dataTableStateManager?.setShowLoading(false);
    });
  }

Execution Environment

Flutter version Flutter (Channel stable, 3.0.2)

PlutoGrid version PlutoGrid version is 5.0.4

OS macOS 12.4 21F79 darwin-x64

elgsylvain85 avatar Aug 21 '22 10:08 elgsylvain85

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] avatar Sep 20 '22 11:09 github-actions[bot]

@elgsylvain85 You need to create a statefulWidget for the footer widget and handle updates by listening for state changes from that widget. Don't try to update the footer widget with setCreateFooter.

bosskmk avatar Sep 26 '22 22:09 bosskmk

@bosskmk According your feedback and with this below code, I can now see update from footer but do you think that "addListener" is the correct listening method ? It works but now "setState" is now called with any event and not only with "data" update.

import 'package:flutter/material.dart';
import 'package:pluto_grid/src/manager/pluto_grid_state_manager.dart';

class DataTableFooter extends StatefulWidget {
  final Widget Function() buildWidget;
  final PlutoGridStateManager stateManager;

  const DataTableFooter(this.buildWidget, this.stateManager, {Key? key})
      : super(key: key);

  @override
  State<StatefulWidget> createState() => _DataTableFooterState();
}

class _DataTableFooterState extends State<DataTableFooter> {
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();

    widget.stateManager.addListener(() {
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return widget.buildWidget();
  }
}

elgsylvain85 avatar Sep 28 '22 18:09 elgsylvain85

When processing with stateManager.addListener, manage the existing and changed states by yourself, and call setState only when necessary.

Call setState with the PlutoGrid(onChanged) callback to handle updates on cell value changes.

bosskmk avatar Sep 28 '22 19:09 bosskmk