Home > Mobile >  save filters from previous requests
save filters from previous requests

Time:03-27

I have a code that is responsible for filtering users by certain parameters.

That is, the resource administrator can select parameters in the filter window, click the 'APPLY' button and the filters will be applied.

Only I would like the state of the filters to be saved, and the next time the administrator opens the filter window, he would not have to select everything again, but he could continue working with the filters selected the previous time.

This is the code responsible for building the for the filters

class UsersPage extends StatefulWidget {
  const UsersPage({Key? key}) : super(key: key);

  @override
  State<UsersPage> createState() => _UsersPageState();
}

class _UsersPageState extends State<UsersPage> {
  Map<String, List<String>?> currentFilters = {};

  // The function is responsible for what parameters will be filtered.
  void _filter(Map<String, List<String>?> filters) {
    setState(() {});
  }
  _goBack(BuildContext context) {
    Navigator.pop(context);

  }
  // Page builder.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          iconTheme: const IconThemeData(color: Colors.white, size: 40),
          // AppBar includes a second AppBar with signature 'Device list'
          bottom: PreferredSize(
              child: AppBar(
                shadowColor: Colors.transparent,
                automaticallyImplyLeading: false,
                backgroundColor: Colors.yellow[600],
                title: const Text('User list',
                    style: TextStyle(
                        fontSize: 30,
                        fontWeight: FontWeight.w800,
                        color: Colors.black)),
                centerTitle: true,
                iconTheme: const IconThemeData(color: Colors.white, size: 40),
                actions: [
                  IconButton(
                    // By clicking on the device card,
                    // you go to the page with a description of this device
                    icon: const Icon(
                      Icons.filter_alt,
                      size: 40.0,
                    ),
                    splashRadius: 25,
                    color: Colors.black,
                    onPressed: () {
                      showDialog<FilterItem>(
                          context: context,
                          builder: (_) {
                            return FilterDialogUser(
                              // Here the already filtered list returns to the page
                              initialState: currentFilters,
                              onApplyFilters: _filter,
                            );
                          });
                    },
                  ),
                ],
              ),
              preferredSize: const Size.fromHeight(kToolbarHeight)),
          leading: IconButton(
            icon: const Icon(Icons.arrow_back_ios),
            splashRadius: 20,
            iconSize: 20.0,
            onPressed: () {
              _goBack(context);
            },
          ),
          automaticallyImplyLeading: true,
          backgroundColor: Colors.black,
          title: Image.asset("assets/images/itrex_logo_for_listdevices.png",
              width: 100, height: 50, color: Colors.white),

          centerTitle: true,
        ),
        // Devices are displayed in the body of the page
        body: ListUsers(filters: currentFilters),
        // This is where the menu options (hamburger button) are defined.
        endDrawer: HamburgerMenu());
  }
}

class FilterItem {
  final String text;
  bool selected;
  List<FilterItem> subitems;

  FilterItem(
      this.text, {
        this.selected = false,
        this.subitems = const [],
      });
}

And the next part of the code is responsible for building a window for filters. (I already tried some of the options for before asking this question, but they were unsuccessful.)

class FilterDialogUser extends StatefulWidget {
  final void Function(Map<String, List<String>?>) onApplyFilters;

  final Map<String, List<String>?> initialState;

  const FilterDialogUser({
    Key? key,
    required this.onApplyFilters,
    this.initialState = const {},
  }) : super(key: key);

  @override
  State<FilterDialogUser> createState() => _FilterDialogUserState();
}

class _FilterDialogUserState extends State<FilterDialogUser> {
  Map<String, List<String>?> filters = {};
  List<bool> isClickedCountry = List.filled(3, false);

  @override
  void initState() {
    super.initState();
    filters = widget.initialState;
  }

  List<FilterItem> children = [
    FilterItem('Georgia', subitems: [
      FilterItem('Tbilisi'),
      FilterItem('Batumi'),
    ]),
    FilterItem('Poland', subitems: [
      FilterItem('Warsaw'),
      FilterItem('Krakow'),
      FilterItem('Wroclaw'),
    ]),
    FilterItem('Armenia', subitems: [
      FilterItem('Erevan'),
      FilterItem('Gyumri'),
    ]),
  ];

  // Building a dialog box with filters.
  @override
  Widget build(BuildContext context) {
    return SimpleDialog(
        title: const Text('Filters',
            textAlign: TextAlign.center,
            style: TextStyle(
              fontSize: 25,
              fontFamily: 'SuisseIntl',
            )),
        contentPadding: const EdgeInsets.all(16),

        // Defining parameters for filtering.
        children: [
          Column(
            children: children.map(
              (e) {
                final int index = children.indexOf(e);
                return Column(
                  children: [
                    InkWell(
                      onTap: () async {
                        setState(() {
                          isClickedCountry[index] = !isClickedCountry[index];
                        });
                      },
                      child: Row(
                        children: [
                          Checkbox(
                            value: e.selected,
                            onChanged: (value) => setState(() {
                              for (var element in e.subitems) {
                                element.selected = value as bool;
                              }
                              e.selected = value as bool;
                            }),
                          ),
                          Text(e.text),
                          const Spacer(),
                          isClickedCountry[index]
                              ? const Icon(Icons.arrow_circle_up)
                              : const Icon(Icons.arrow_circle_down)
                        ],
                      ),
                    ),
                    if (e.subitems.isNotEmpty)
                      !isClickedCountry[index]
                          ? Container()
                          : Padding(
                              padding: const EdgeInsets.fromLTRB(30, 0, 0, 0),
                              child: Column(
                                children: e.subitems.map((e) {
                                  return Row(children: [
                                    Checkbox(
                                      value: e.selected,
                                      onChanged: (value) => setState(() {
                                        e.selected = value as bool;
                                      }),
                                    ),
                                    Text(e.text),
                                  ]);
                                }).toList(),
                              ),
                            )
                  ],
                );
              },
            ).toList(),
          ),
          const SizedBox(
            height: 5,
          ),
          ElevatedButton(
              onPressed: () {
                Navigator.of(context).pop();
                widget.onApplyFilters(filters);
              },
              child: const Text('APPLY', style: TextStyle(color: Colors.black)),
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all(Colors.grey),
              )),
        ]);
  }
}

CodePudding user response:

All you have to do is use a database, by default Flutter Secure Storage or Shared Preferences is used to store settings, but if you have too many user settings (more than 100) you can try using Sqflite, Hive or Objectbox. When the administrator selects search settings, you must save them to the database and retrieve them at the next login and place them as default values.

CodePudding user response:

I'm having problems with Shared Preferences on my computer, so I'll show Flutter Secure Storage, it's basically the same, except that Flutter Secure Storage has built-in security and is slightly more performant.

First you need to include the dependency in pubspec.yaml:

flutter_secure_storage: ^5.0.2

Then create file secure_storage.dart:

import 'package:flutter_secure_storage/flutter_secure_storage.dart';

class SecureStorage {
  // Create an instance and enable secure encryption:
  static const storage = FlutterSecureStorage(
      aOptions: AndroidOptions(encryptedSharedPreferences: true));

  static Future<void> saveData(String key, String value) async {
    await storage.write(key: key, value: value);
  }

  static Future<String?> readData(String key) async {
    return await storage.read(key: key);
  }

  static Future<Map<String, String>> readAllData(String key) async {
    return await storage.readAll();
  }

  static Future<bool> containsData(String key) async {
    return await storage.containsKey(key: key);
  }

  static Future<void> deleteData(String key) async {
    await storage.delete(key: key);
  }

  static Future<void> deleteAllData() async {
    await storage.deleteAll();
  }
}

And then you can access the SecureStorage class whenever you want because it has static methods. For example, with this command in any of the methods or widgets you can save your filter after the administrator selects it:

SecureStorage.saveData("filter", filterValue);

Example of read:

  static var filterValue; // Declare a variable

  @override
  void initState() {
    super.initState();
    initSettings(); // Call initialization in initState()
  }

  void initSettings() async {
    filterValue = await SecureStorage.readData("filter"); // Read value
  }
  • Related