bosskmk / pluto_grid

PlutoGrid is a dataGrid for flutter that can be controlled by the keyboard on desktop and web. Of course, it works well on Android and IOS.
https://pluto.weblaze.dev
MIT License
637 stars 291 forks source link

[Bug] PlutoGrid data is not persistent when using it with tabs, #940

Closed jesussmile closed 8 months ago

jesussmile commented 9 months ago

How to make plutogrid cell value persistent when switching tabs ? For example i have 3 tabs in the code below, when i am in the first tab and enter some value in the cell and then come back to it, the plutogrid is rebuilt, removing the data, i want it to be persistent, i tried different methods like global variable, providers, river pod etc.. but just doesn't work with tabs

this is the code, can you take a look?


class WeeklyRoster extends StatefulWidget {
  @override
  State<WeeklyRoster> createState() => _WeeklyRosterState();
}

class _WeeklyRosterState extends State<WeeklyRoster>
    with AutomaticKeepAliveClientMixin {
  List<Map<String, dynamic>>? captainData;
  List<Map<String, dynamic>>? firstOfficerData;
  List<Map<String, dynamic>>? cabinCrewData;
  PlutoGridStateManager? _stateManager;
  List<PlutoColumn>? columns;
  List<PlutoRow>? plutoRows;
  List<Map<String, dynamic>>? _globalData;
  String globalType = "captain";
  DateTimeRange _dateRange = DateTimeRange(
    start: DateTime.now(),
    end: DateTime.now().add(const Duration(days: 10)),
  );
  @override
  void initState() {
    super.initState();
    captainData =
        Provider.of<RosterDataProvider>(context, listen: false).captainSnapShot;
    firstOfficerData = Provider.of<RosterDataProvider>(context, listen: false)
        .firstOfficerSnapShot;
    cabinCrewData = Provider.of<RosterDataProvider>(context, listen: false)
        .cabinCrewSnapShot;
    _globalData = captainData;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).primaryColor,
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text('Weekly Schedule'),
            IconButton(
              onPressed: () async {
                final picked = await showDateRangePicker(
                  context: context,
                  firstDate: DateTime(2015, 8),
                  lastDate: DateTime(2101),
                  initialDateRange: _dateRange,
                );
                if (picked != null && picked != _dateRange) {
                  setState(() {
                    _dateRange = picked;
                  });
                  _parseColumnRow(
                    _globalData,
                    globalType,
                    _dateRange.start,
                    _dateRange.end,
                  );
                }
              },
              icon: const Icon(Icons.calendar_today),
            ),
          ],
        ),
        bottomOpacity: 1,
        elevation: 0,
        automaticallyImplyLeading: false,
      ),
      body: DefaultTabController(
        length: 3,
        child: Column(
          children: [
            SizedBox(
              height: 50,
              child: TabBar(
                onTap: (value) {
                  switch (value) {
                    case 0:
                      _globalData = captainData;
                      globalType = "captain";
                      break;
                    case 1:
                      _globalData = firstOfficerData;
                      globalType = "firstOfficer";
                      break;
                    case 2:
                      _globalData = cabinCrewData;
                      globalType = "cabinCrew";
                      break;
                  }
                },
                tabs: const [
                  Tab(text: 'Captain'),
                  Tab(text: 'Copilot'),
                  Tab(text: 'Cabin Crew'),
                ],
                indicatorColor: const Color.fromARGB(255, 102, 249, 4),
                indicatorSize: TabBarIndicatorSize.label,
              ),
            ),
            Expanded(
              child: TabBarView(
                children: [
                  buildGrid(captainData!, "captain", context),
                  buildGrid(firstOfficerData!, "firstOfficer", context),
                  buildGrid(cabinCrewData!, "cabinCrew", context),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  PlutoGrid buildGrid(
      List<Map<String, dynamic>> data, String type, BuildContext context) {
    return PlutoGrid(
      mode: PlutoGridMode.selectWithOneTap,
      onSelected: (event) {
        final PlutoRow row = _stateManager!.rows.elementAt(event.rowIdx!);
        final String userId = row.cells['NAME']!.value.toString();
        final String firestoreCollection = type == "captain"
            ? "CAPTAIN_DATA"
            : type == "firstOfficer"
                ? "FIRST_OFFICER_DATA"
                : "CABIN_CREW_DATA";
        openDetail(event.cell, event.cell!.column.field, userId,
            firestoreCollection, context);
      },
      onLoaded: (PlutoGridOnLoadedEvent event) {
        _stateManager = event.stateManager;
        _parseColumnRow(data, type, _dateRange.start, _dateRange.end);
      },
      columns: columns ?? [],
      rows: plutoRows ?? [],
    );
  }

  void _parseColumnRow(
    List<Map<String, dynamic>>? data,
    String type,
    DateTime startDate,
    DateTime endDate,
  ) async {
    if (columns != null) {
      _stateManager!.removeColumns(columns!);
    }
    if (plutoRows != null) {
      _stateManager!.removeAllRows();
    }
    final columnTitles = List.generate(
      endDate.difference(startDate).inDays + 1,
      (index) =>
          DateFormat('dd MMM').format(startDate.add(Duration(days: index))),
    );
    columns = [
      PlutoColumn(
        title: 'NAME',
        field: 'NAME',
        type: PlutoColumnType.text(),
        width: 200,
      ),
    ];
    for (int i = 0; i < columnTitles.length; i++) {
      columns!.add(
        PlutoColumn(
          title: columnTitles[i],
          field: '$i',
          type: PlutoColumnType.text(),
          width: 100,
        ),
      );
    }
    plutoRows = [];
    final name = data!.map((e) {
      return e['NAME'];
    }).toList();
    for (int i = 0; i < name.length; i++) {
      String cap = "${name[i]} ";
      Map<String, PlutoCell> cells = {
        'NAME': PlutoCell(value: cap),
      };
      for (int j = 0; j < columnTitles.length; j++) {
        cells['$j'] = PlutoCell(value: '');
      }
      plutoRows!.add(PlutoRow(cells: cells));
    }
    await PlutoGridStateManager.initializeRowsAsync(
      columns!,
      plutoRows!,
    ).then((value) {
      _stateManager!.removeAllRows();
      _stateManager!.insertColumns(0, columns!);
      _stateManager!.appendRows(plutoRows!);
      _stateManager!.notifyListeners();
    });
  }
}
github-actions[bot] commented 8 months ago

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