How to keep data persistent when switching tabs?

73 Views Asked by At

I have a Tab with 3 nested tabs ? when i switch from one tab to another the data that i entered in tab 1 is not peristent,

I am working with PlutoGrid this is the code below


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) {
    super.build(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;
                  });
                  // print('reach Date select weekly');
                  // print(' _globalData $_globalData');
                  _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:
                      // print('on captain tab');
                      //  _globalData?.clear();
                      _globalData = captainData;
                      globalType = "captain";
                      // });
                      break;
                    case 1:
                      //  _globalData?.clear();
                      _globalData = firstOfficerData;
                      globalType = "firstOfficer";
                      break;
                    case 2:
                      //  _globalData?.clear();
                      _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: [
                  PlutoGrid(
                    key: const ValueKey('captain'),
                    mode: PlutoGridMode.selectWithOneTap,
                    onSelected: (event) {
                      final PlutoRow row =
                          _stateManager!.rows.elementAt(event.rowIdx!);
                      final String userId = row.cells['NAME']!.value.toString();
                      const String firestoreCollection = "CAPTAIN_DATA";

                      openDetail(event.cell, event.cell!.column.field, userId,
                          firestoreCollection, context);
                    },
                    onLoaded: (PlutoGridOnLoadedEvent event) {
                      _stateManager = event.stateManager;
                      _parseColumnRow(captainData, 'captain', _dateRange.start,
                          _dateRange.end);
                    },
                    columns: columns ?? [],
                    rows: plutoRows ?? [],
                  ),
                  PlutoGrid(
                    key: const ValueKey('firstOfficer'),
                    mode: PlutoGridMode.selectWithOneTap,
                    onSelected: (event) {
                      final PlutoRow row =
                          _stateManager!.rows.elementAt(event.rowIdx!);
                      final String userId = row.cells['NAME']!.value.toString();
                      const String firestoreCollection = "FIRST_OFFICER_DATA";

                      openDetail(event.cell, event.cell!.column.field, userId,
                          firestoreCollection, context);
                    },
                    onLoaded: (PlutoGridOnLoadedEvent event) {
                      _stateManager = event.stateManager;
                      _parseColumnRow(firstOfficerData, 'firstOfficer',
                          _dateRange.start, _dateRange.end);
                    },
                    columns: columns ?? [],
                    rows: plutoRows ?? [],
                  ),
                  PlutoGrid(
                    key: const ValueKey('cabinCrew'),
                    mode: PlutoGridMode.selectWithOneTap,
                    onSelected: (event) {
                      final PlutoRow row =
                          _stateManager!.rows.elementAt(event.rowIdx!);
                      final String userId = row.cells['NAME']!.value.toString();
                      const String firestoreCollection = "CABIN_CREW_DATA";

                      openDetail(event.cell, event.cell!.column.field, userId,
                          firestoreCollection, context);
                    },
                    onLoaded: (PlutoGridOnLoadedEvent event) {
                      _stateManager = event.stateManager;
                      _parseColumnRow(cabinCrewData, 'cabinCrew',
                          _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();
    });
  }

  openDetail(PlutoCell? cell, String field, String userId,
      String firestoreCollection, BuildContext context) async {
    await showDialog(
      context: context,
      builder: (BuildContext context) {
        return Builder(
          builder: (BuildContext context) {
            return SizedBox(
              height: 600,
              width: 200,
              child: AlertDialog(
                title: const Text('Select a shift'),
                content: SizedBox(
                  height: 500,
                  width: 200,
                  child: ListView.builder(
                    itemCount: shift.length,
                    itemBuilder: (BuildContext context, int index) {
                      final s = shift[index];
                      return ListTile(
                        title: Text(s),
                        onTap: () {
                          cell!.value = s;
                          Navigator.of(context).pop();
                        },
                      );
                    },
                  ),
                ),
              ),
            );
          },
        );
      },
    );
  }

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;
}

as I go to the first tab Captain then enter some value in the cell , switch to another tab and come back that entry is gone, i have tried many ways like using provider, global variable, AutomaticKeepAliveMixin etc but failed, Any help ?

1

There are 1 best solutions below

8
Autocrab On
  1. Move PlutoGrid out of function and use it directly in TabBarView

  2. Add keys to all 3 pluto widgets, for example key: ValueKey('pluto1'), key: ValueKey('pluto2') and key: ValueKey('pluto3')

  3. Add AutomaticKeepAliveClientMixin mixin to PlutoGrid's state and override bool get wantKeepAlive => true; or use it with KeepAlive widget:

    KeepAlive(
                keepAlive: true,                  
                child: PlutoGrid(
                  key: const ValueKey('captain'),
                     mode: PlutoGridMode.selectWithOneTap,
                     onSelected: (event) {
                       final PlutoRow row =
                           _stateManager!.rows.elementAt(event.rowIdx!);
                       final String userId = row.cells['NAME']!.value.toString();
                       const String firestoreCollection = "CAPTAIN_DATA";
    
                       openDetail(event.cell, event.cell!.column.field, userId,
                           firestoreCollection, context);
                     },
                     onLoaded: (PlutoGridOnLoadedEvent event) {
                       _stateManager = event.stateManager;
                       _parseColumnRow(captainData, 'captain', _dateRange.start,
                           _dateRange.end);
                     },
                     columns: columns ?? [],
                     rows: plutoRows ?? [],
                   )
               )